**场景:**创建一个Animal类,有Dog和Cat类继承Animal类,并重写say( )方法,创建一个Woman类,该类有个Animal类型的成员变量和一个pet( )方法调用对应的say( )方法
package com.sukai.test01;
/**
* 实现多态
*/
public class Animal {
public static void main(String[] args) {
Woman womanA = new Woman(new Cat());
womanA.Pet();
Woman womanB = new Woman(new Dog());
womanB.Pet();
Woman womanC = new Woman(new Animal());
womanC.Pet();
}
public void say() {
System.out.println("I am a animal");
}
}
class Dog extends Animal {
@Override
public void say() {
System.out.println("I am a dog");
}
}
class Cat extends Animal {
@Override
public void say() {
System.out.println("I am a cat");
}
}
class Woman {
private Animal animal;
Woman(Animal animal) {
this.animal = animal;
}
public void Pet() {
animal.say();
}
}
经发现,womanA.Pet();
本质上调用的是运行时类的say()
方法而不是引用类型的say()
Human human = new Man();
虽然我们new的对象是一个Man()
但是它调用的却是Animal()
的Say()
方法
package com.sukai.test01;
public class Human {
public static void main(String[] args) {
Human human = new Man();
human.Say();
}
public void Say() {
System.out.println("I am a human");
}
}
class Man extends Human {
@Override
public void Say() {
System.out.println("I am a man");
}
}
内存分析:
如图所示,首先在栈中创建一个变量,它指向Man这个对象,但是由于在调用构造方法时,是把human当成一个Human对象的引用传过来的,所以human只能指向Man对象里面的Human对象,那么现在我们调用human.say()
,它就回去代码区中找say( )方法,现在它发现有两个Say( ),那么要调用哪一个呢?此时实际上在父类的内部有一个指向Say( )方法的指针,在程序运行期间,你new的是哪个对象,指针就指向哪个对象的Say( )方法,这就是动态绑定,通过这种动态绑定的方式就可以实现多态了
总结动态绑定(多态):动态绑定是指在“执行期间”(而非编译期间)判断所引用的实际对象类型,根据其实际的类型调用其相应的方法