面向对象特征之三:多态性
一、多态性的理解
1、理解多态性:可以理解为一个事务的多种形态
2、何为多态性:
对象的多态性,父类的引用指向子类的对象(或子类的对象给父类引用)
3、多态性的使用:虚拟方法的使用
有了对象的多态性以后,我们在编译期,只能用父类声明的方法,但在运行期
我们实际执行的是子类重写的方法。
总结:编译,看左边 ;运行,看右边
4、多态性的使用前提
类的继承关系
方法的重写
5、对象的多态性,只适用于方法,不适用于属性
结果:编译和运行都看左边
面试题:重载和重写的区别
重载:早绑定,静态绑定,即在方法调用前,编译器就已经确定了做要调用的方法。
重写:晚绑定,动态绑定,即方法的调用,在运行时才确定
-
在多态情况下,父类被重写的方法加虚拟方法,父类根据赋给他的;不同字类对象,
-
动态调用属于子类的方法,这样的方法调用在编译期是无法确定的。
二、instance of 关键字的使用(向下转型)
1、 格式:a instance of A /判断对象a是否是类A的实例,如果是,返回true ; 如果不是,返回false.
2、使用情境,为了避免在向下转型之前出现ClassExcpetion的异常,我们在向下转型之前,先用instanceof的判断,一旦返回true,就进行向下转型,如果返回false,不进行向下转型
3、若 a instanceof A返回true / aintanceofB也返回true则类B是类A的父类
三、完整示例
1、示例
public class PersonTest {
public static void main(String[] args) {
//这就是多态性,调用Person的子类Man
Person p1 = new Man();
p1.eat();//显示Man中重写的方法,猛男吃饭
p1.walk();//显示Man中重写的方法,猛男走路
//p1.run(); /编译不通过,只有父类中声明过的方法才能调用
System.out.println(p1.age);//1 ,父类
//*****************************************************************************************
/* 如何调用子类特有的方法、属性
* 有了对象的多态性以后,内存中实际上是加载了子类特有的属性和方法的,但是由于
* 声明为父类类型,导致编译时只能调用父类中声明的属性和方法,子类中特有的属性和方法
* 不能调用。
*
* > 强制类型转换(向下转型)
* > 多态性(向上转型)
*
* ps:同级直接不可以转换,会出现ClassCastException异常
*
*/
//强制类型转换(向下转型)
Man m1 = (Man)p1;
m1.run();//可以调用子类中特有的属性和方法了
m1.dance();//也可以调父类中的方法
m1.eat();//但是被重写的方法还是调用子类中的
//****************************************************************************
//instance of 的使用
if(p1 instanceof Man){
Man m2 = (Man)p1;
m2.run();//进去了
}
if(p1 instanceof Woman){
Woman w1 = (Woman)p1;
w1.shopping();//没有输出结果,没进去
//没有实例化
}
if(p1 instanceof Object){
System.out.println("进来了");//进去了,Object是Person的父类
}
}
}
2、习题1
问题一:编译时通过,运行时不通过
要想通过,一般只能new 子类的对象
Person p3 = new Woman();
Man m3 = (Man)p3;
Person p4 = new Person();
Man m4 = (Man)p4;
问题二:编译通过,运行时也通过
Object obj = new Woman();
Person p = (Person)obj;
问题三:编译不通过
Man m5 = new Woman(); //同级关系
String str = new Date();//Date 是 String 的子类