如果构造出Lady对象的pet是Cat对象c,这个c首先会向上转型为Animal类,也就是说Lady的pet属性虽然指向的是"Cat c"对象,但它只能看见其中的父对象Animal部分。那么myPetSing(pet.sing();)方法自然会调用Animal类的sing()方法。以上过程是编译器所认为的过程,也是静态绑定或前期绑定的过程。
但编译完成后,虽然pet属性只能看见Animal部分,但实际在执行时pet.sing()却换转换为执行c.sing()。就相当于做了一次对象类型强制转换Cat petx = (Cat)pet。这是动态绑定或后期绑定的过程,也称为多态。
实际上,对象在被new出来后,它所涉及到的方法都放在code segment内存区中的一个方法列表中,这个列表中包含了子类、父类的方法,只不过有些时候不可见的方法无法去调用。当执行程序时,内部的机制可以从方法列表中搜索出最符合环境的方法并执行它。
实现多态的技术的关键点在于:
(1).定义一个父类引用f,并将其指向子类对象,即进行向上转型;
(2).重写父类的方法,并使用父类引用f去引用这个方法。这样就可以面向父类进行编程。
正如上面的示例中,将pet定义为Animal类而非具体的子类,并在方法中调用pet.sing()。如此依赖,就无需考虑pet到底是Cat/Dog,在进行功能扩展添加Bird类时,完全不用再修改Lady类的这段代码。
再例如,父类Animal,子类Dog,方法sing()。
class Animal {public void sing(A);} class Dog extends Animal {public void sing(B);} public class Test { Animal a = new Dog(); //父类引用变量a指向子对象Dog,此时将向上转型 a.sing(); //使用父类引用变量a引用被重写的方法sing(),执行时将动态绑定到Dog的sing() }