0%

面向对象进阶-多态

多态:多种形态,即,同种类型的对象,表现出得不太形态

1
2
Student s = new Student();
Person p = new Student();

应用场景:多种权限的用户注册时。

表现形式:父类类型 对象名称 = 子类对象;

多态的前提:1.有继承关系;

​ 2.有父类引用指向子类对象(Fu f = new Zi();)

​ 3.有方法重写;

多态的好处:使用父类型作为参数,可以接收所有子类对象,体现多态的扩展性与便利。

多态调用成员的特点:

变量调用:编译看左边,运行也看左边

​ 编译看左边: javac编译代码的时候,会看左边的父类中有没有这个变量,如果有,编译成功,如果没有编译失败。

​ 运行看左边:java运行代码时,实际获取的就是左边父类中成员变量的值。

方法调用:编译看左边,运行看右边
​ 编译看左边:javac编译代码时侯,会看左边的父类中有没有这个方法,如果有,编译成功,如果没有编译失败

​ 运行看右边:Java运行代码的时候,实际上运行的是子类中的方法

​ 如何理解?

​ Animal a = new Dog();

​ 成员变量:在子类对象中,会把父类的成员变量也继承下来。父:name,子:name

​ 成员方法:如果子类对方法进行重写,那么在虚方法表中是会把父类的方法进行覆盖的。

多态的优势和弊端:

​ 优势:

​ 1. 在多态形式下,右边对象可以 实现解耦合,便于扩展和维护。

1
2
Person p = new  Student();  //Person p = new Teacher();
p.work();//业务逻辑发生改变时,后续代码无需修改

​ 2. 定义方法时,使用父类型作为参数,可以接收所有子类对象,体现多态的扩展性与便利

​ 弊端:

不能直接调用子类的特有功能

​ 原因:当调用成员方法的时候,编译看左边,运行看右边,那么在编译的时候会先检查左边的父类中有没有这个方法,如果没有直接报错.

​ 解决方案:变回子类类型

​ 转换时如果转成其他类型,就会报错//Cat c = (Cat) a;

1
2
3
Animal a = new Dog();
Dog d = new Dog();
d.lookhome();
1
2
3
4
5
6
7
8
9
10
//避免转换类型与真实对象类型不一致会报错的解决方案
if(a instanceof Dog){//Animal a = new Dog();
Dog d = (Dog) a;
d.lookHome();
}else if(a instanceof Cat){//Animal a = new Cat();
Cat c = (Cat) a;
c.catMouse();
}else{
System.out.println("没有这个类型,无法转换");
}

JDK14新特性—判断和强转的合并.

先判断a是否为Dog类型,如果是,则强转为Dog类型,转换之后的变量名为d

如果不是,则不强转,结果直接为false

1
2
3
4
5
6
7
if(a instanceof Dog d){//Animal a = new Dog();
d.lookHome();
}else if(a instanceof Cat c){//Animal a = new Cat();
c.catMouse();
}else{
System.out.println("没有这个类型,无法转换");
}