多态的浅显理解
Contents
多态:
-
定义:一个对象变量(对象引用)可以指向多个实际类型的现象称为多态。
- 例如:父类引用指向子类对象,父类引用可以指向父类对象。但是子类引用不能指向父类对象
-
对象引用调用的方法究竟属于哪一个对象(实际类型)是在运行期间动态确定的,这称为动态绑定。
- 当父类引用指向子类对象。如果子类重写了父类的方法,真正执行的是子类覆盖的方法,如果子类没有覆盖父类的方法,执行的是父类的方法。
例:
son的实际类型是Son,它是Father的子类。如果Son定义了方法(重写)method1,则调用Son中的method1,否则调用Father中的method1。这是在运行期间动态决定的。
|
|
理解在方法调用时发生了什么?
虚拟机预先为每一个类创建了一个方法表,其中列出了所有的方法签名和调用的实际方法
|
|
在调用方法时,如:
|
|
首先根据son的实际类型来获取方法表:
|
|
虚拟机在方法表中查找定义了method1()签名的类。确定应该调用的方法:Son.method1()。
在调用方法:如
|
|
根据father的实际类型来获取方法表:这里father的实际类型为Father。
|
|
虚拟机在方法表中查找定义了method1()签名的类。确定应该调用的方法:Father.method1()。但是由于Son已经将method1()进行重写了,所以实际上调用的是Son.method1()
小结:
多态存在的条件:
- 继承->父类和子类
- 子类重写父类中的方法->
- 父类引用指向子类对象
当父类引用指向子类对象时,原则上来说只能调用父类中的方法,但是一旦子类重写了父类的方法,就可以调用子类中的方法。这就是多态
再举个例子
|
|
这里输出的是son’s method 1。这里满足了多态的三个条件:继承,父类引用指向子类对象,子类重写父类方法。因此在调用father.method1();时,实际上是动态绑定到了子类的method1方法上。
多态的特点:
- 对象类型和引用类型之间具有继承(类)/实现(接口)的关系;
- 对象类型不可变,引用类型可变;
- 方法具有多态性,属性不具有多态性;
- 引用类型变量发出的方法调用的到底是哪个类中的方法,必须在程序运行期间才能确定;
- 多态不能调用“只在子类存在但在父类不存在”的方法;
- 如果子类重写了父类的方法,真正执行的是子类覆盖的方法,如果子类没有覆盖父类的方法,执行的是父类的方法。