java - 不清楚动态绑定
问题描述
我不正确理解动态绑定和覆盖的概念:
这是一些代码:
class Cake {
public void taste (Cake c) {
System.out.println("In taste of Cake class");
}
}
class ChocolateCake extends Cake {
public void taste(Cake c) {
System.out.println("In taste (Cake version) of ChocolateCake class");
}
public void taste(ChocolateCake cc) {
System.out.println("In taste (ChocolateCake version) of ChocolateCake class");
}
}
public static void main(String[] args)
{
ChocolateCake cc = new ChocolateCake();
Cake c = new ChocolateCake();
Cake c1 = new Cake();
Cake c2 = new ChocolateCake();
c1.taste(cc);
c1.taste(c);
c2.taste(cc);
c2.taste(c);
}
我期望:
In taste of Cake class
In taste of Cake class
In taste (ChocolateCake version) of ChocolateCake class" <----
In taste (Cake version) of ChocolateCake class
实际的:
In taste of Cake class
In taste of Cake class
In taste (Cake version) of ChocolateCake class <----
In taste (Cake version) of ChocolateCake class
如果对象是 ChocolateCake 类型并且我调用 cc 也是 ChocolateCake,编译器怎么会显示它正在获取 Cake 作为参数?
解决方案
这是因为 Java 使用静态和动态绑定来选择在这种情况下调用的方法。
有问题的线是这个,对吧?
c2.taste(cc);
编译器首先选择调用哪个方法(静态绑定)。由于c2
是 compile time type Cake
,编译器只看到taste(Cake)
方法。所以它说“呼叫taste(Cake)
”。
现在在运行时,运行时需要taste(Cake)
根据c2
. 这是动态绑定。它会选择 中的那个Cake
吗?还是里面的那个ChocolateCake
?由于c2
is 是运行时类型ChocolateCake
,它调用taste(Cake)
in的实现ChocolateCake
。
如您所见,您认为会调用的方法 - taste(ChocolateCake)
- 甚至没有被提及!这是因为这是taste
方法的不同重载,并且因为它在ChocolateCake
类中,编译器看不到。为什么编译器看不到?因为c2
是编译时类型Cake
。
简而言之,编译器决定哪个重载,运行时决定哪个实现。
回应您的陈述:
如果对象是 ChocolateCake 类型...
只有你知道对象是 type ChocolateCake
。编译器没有。它只知道c2
是类型Cake
,因为这就是它的声明所说的。