动态绑定和多态
先记录下包含的知识点:
- 动态绑定是指:在执行期间(而非编译期)判断所引用对象的实际类型,根据其实际的类型调用其相应的方法”
动态绑定有个前提:
- 要有继承
- 要有重写
- 父类引用指向子类对象
举个例子,先定义四个类
class Animal
{
public String name;
Animal(String name)
{
this.name=name;
}
public void enjoy()
{
System.out.println("叫声...");
}
}
class Cat extends Animal
{
public String eyesColor;
Cat(String n,String c){
super(n);
this.eyesColor=c;
}
public void enjoy()
{
System.out.println("猫叫声...");
}
}
class Dog extends Animal
{
public String furColor;
Dog(String n,String f){
super(n);
this.furColor=f;
}
public void enjoy()
{
System.out.println("狗叫声...");
}
}
class Lady
{
private String name;
private Animal pet;
Lady(String name,Animal pet)
{
this.name=name;
this.pet=pet;
}
public void myPetEnjoy(){
pet.enjoy();
}
}
主程序
class TestPolymoph
{
public static void main(String[] args)
{
//Dog d=new Dog("dogname","black");
//Lady l2=new Lady("li2",d);
//l2.myPetEnjoy(); //狗叫声。。。
Cat c=new Cat("catname","blue");
Lady l1=new Lady("li1",c);
l1.myPetEnjoy(); //猫叫声。。。
}
}
在这里我们有个疑问了,我们的Lady传入一个Animal对象
在执行这一句
l1.myPetEnjoy();
调用的是Animal中的enjoy方法。为什么不是调用这一句代码呢?
System.out.println("叫声...");
我们来分析一下,先上图:
- 在栈区新建了一个猫对象 “c”
- 先给调用基类方法的构造函数,把catname赋值给基类的Name字段
- 类在编译时会把类中的方法放在代码区,code sig 里面存在着Animal中的方法和cat中的方法
- 初始化调用基类构造函数时,基类中有个方法指针,这个的时候是指向Animal的代码片段的(虚线1)
- 然后调用自身的构造函数时,设置自身的字段后,方法指针指向子类的代码片段(虚线2)
所以这里有个很有意思的现象:
1. Lady中的Pet对象,只能访问Animal中的字段
2. 因为传过去的Pet对象对Animal中的方法进行了重写,导致指针指向了子类中的方法。所以调用这个对象的方法时,执行的是子类的方法片段。
总结一句话:动态绑定是指,实际New了谁的对象,就调用谁的方法。