JavaSE-面向对象之多态
温馨提示:
本文最后更新于 2024年07月21日,已超过 271 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我。
- 多态是什么?
- 同样使用的是父类的引用,调用同一个名称的方法,却可以得到不同的调用结果,这就是Java中的多态。
- 即:同一个函数,多种形态。
- 实际上多态包括动态多态和静态多态。
- 使用多态便于灵活的拓展我们开发的程序。
- 方法覆盖:
- 在类的继承体系结构中,如果子类中出现了与父类中有同原型的方法,那么认为子类中的方法覆盖了父类中的方法(也称为方法重写)。
- 通过子类的实例调用被覆盖的方法时,将总是调用子类的方法,而父类的方法将被隐藏。
- 区分方法覆盖(重写)和方法重载:
- 方法重写一般在父子类中发生,方法重载一般是同一个类中。
- 方法重写是方法名一致,形参类型一致,个数一致,返回值类型一致,而且权限修饰符的权限只能大于或等于父类的方法的权限。
- 可以在方法前面加上@Override检测是否构成重写。
- 方法重载是方法名一样,形参类型不一样,返回值类型无影响,权限修饰符也无影响。
- 方法重写出现的前提是必须要有继承关系发生的情况下。
- 方法重载时,继承不是必须的。
- 方法重写要求父类和子类中的方法必须是同原型,方法重载各方法的原型是不同的。
例如
class Person{ public void run(){ System.out.println("人跑步!!!"); } } class Student extends Person{ public void run(){ System.out.println("学生跑步!!!"); } public void study(){ System.out.prinln("学生学习!!!"); } } class Teacher extends Person{ public void run(){ System.out.println("老师跑步!!!"); } } class TestDemo{ public static void main(String[] args){ Person p = new Student(); //引用转型 p.run(); //调用学生的方法,打印学生跑步!!! Person p2 = new Teacher(); p2.run(); //调用老师的方法,打印老师跑步!!! //p 和 p2都是Person类,但是同样调用run方法, //打印的结果却是不一样,我们称这样的就是多态 //只有运行时候才知道运行哪个方法 //在eclipse中,按住Ctrl键,点p.run();这里会跳转到Person的run方法, //而不是运行的那个run方法,这就是动态多态。(继承是前提!!!) //由上面的结果可以看出,父类引用指向子类对象,调用方法时,调用的是子类的重写后的方法。 //p是无法调用student的study方法,那么,我们要怎么调用子类特有的方法呢? Student st = (Student)p; //类比强制类型转换,上面的子类赋值给父类,就相当与自动转换 st.study(); //打印学生学习!!! //注意这里会出现问题,因为如果把p强制转换成Teacher对象的话, //会报ClassCastException:造型异常 //所以建议强制类型转换是,使用instanceOf进行判断 if(p2 instanceOf Teacher){ Teacher t = (Teacher)p2; } } }
- 由上可以看出:如果不强制转换成子类,那就只能调用父类中定义的方法,如果这个方法被子类覆盖了,那就执行子类中的方法,如果没有,那就调用父类中的方法。
- 如果强制转换了,那就可以调用子类中特有的一些方法,如上面的Student的study方法。
- 静态多态和动态多态:
- 静态多态:
- 静态多态也称为编译时多态,即在编译时决定调用哪个方法;
- 静态多态一般指方法重载;
- 只要构成了方法重载,就可以认为形成了静态多态的条件,静态多态与是否发生了继承没有必然的联系。
- 静态多态在eclipse中,按住Ctrl键,点击调用的方法会跳转到运行的方法。
- 动态多态:
- 动态多态只有在运行时才知道运行哪个方法。
- 继承是动态多态的前提!!!
- 子类要重写方法。
- 动态多态在eclipse中,按住Ctrl键,点击调用的方法,会跳转到父类的方法,而不是执行的子类中的方法。
- 静态多态:
抽象类 abstract
- 使用abstract修饰的类就叫抽象类
- 如果某个类中包含了抽象方法,那么该类就必须定义为抽象类。
- 抽象类中可以有成员变量,成员方法,静态变量,静态方法,构造方法,抽象方法可有可无。
- 抽象类只能用于继承,而且继承的子类要实现父类的所有抽象方法,如果没有实现所有的抽象方法,这个类也为抽象类,只能用于继承,不能直接调用构造方法得到其实例。
- 抽象方法必须为public或者protected,或者默认包权限(因为如果为private,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为包权限;
定义:
权限修饰符 abstract class 类名{ 权限修饰符 abstract 返回值类型 抽象方法名; }
final和abstract,private和abstract,static和abstract,这些是不能放在一起的修饰符
解释:因为abstract修饰的方法是必须在其子类中实现(重写),才能以多态方式调用,以上修饰符在修饰方法时期子类都重写不了这个方法,final是不可以重写,private是不能够继承到子类,所以也就不能重写,static是可以重写的,但是由对象的创建方式,static修饰的是优先于对象创建加载进内存,如果static和abstract一起用的话,子类实现了,但是先要创建父类(有父才有子),所以先加载父类,这时子类还没有创建,当然会出问题。
接口 interface
使用interface定义的就是接口,没有class关键字。
如果某个类中的所有方法都是抽象方法,那么可以考虑将该类定义为接口。
接口比抽象类更抽象,相当于定义了一套规范和标准。
接口不能被直接实例化,只能被接口继承(extends)或被类实现(implements)。
接口中只允许有常量和抽象方法。
- 常量, public static final 常量类型 常量名 = 常量值;
- public static final 可以省略,编译的时候jvm会自动添加。
- 抽象方法,所有权限都是public ,不写的话,默认是public ,可以省略abstract关键字。
实现接口时,如果不实现所有的抽象方法,那就要把这个类定义为抽象类。
类实现接口用implements关键字后面加 接口名1,接口名2,接口名3.
定义:
interface USB{ public void test1(); void test2(); int A = 10; public static final int B = 10; } interface USB2 extends USB{ } abstract class Keyboard1 implements USB2{ public void test2() { } } class Mouse implements USB2{ public void test1() { } public void test2() { } }
抽象类和接口的区别
- 抽象类中可以有抽象方法,也可以没有抽象方法(抽象方法用于约束子类的行为),抽象类中可以包含成员属性和普通方法。一个类中如果包含抽象方法,则这个类必须定义为抽象类,一个类继承抽象类,要么实现所有抽象方法,要么也是抽象类。抽象类有构造方法,但是不能被直接实例化,之能用于子类调用,抽象类必须被继承。抽象类的抽象方法不写权限修饰符默认为包权限。
- 接口中只有常量和抽象方法,不能包含其他的。一个类不能继承多个抽象类,但是可以给同时实现多个接口。借助接口可以实现多继承的效果。接口中的所有东西都是public访问权限。
正文到此结束
- 本文标签: Java
- 本文链接: https://fxyh.top/article/17
- 版权声明: 本文由fxyh原创发布,转载请遵循《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权