我不了解动态绑定和适当覆盖的概念:
这是一些代码:
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);
}
Run Code Online (Sandbox Code Playgroud)
我期望:
In taste of Cake class
In taste of Cake class
In taste (ChocolateCake version) of ChocolateCake class" <----
In taste (Cake version) of ChocolateCake class
Run Code Online (Sandbox Code Playgroud)
实际:
In taste of Cake class
In taste of Cake class
In taste (Cake version) of ChocolateCake class <----
In taste (Cake version) of ChocolateCake class
Run Code Online (Sandbox Code Playgroud)
如果对象的类型为ChocolateCake,并且我将cc称为ChocolateCake,那么编译器如何显示它正在将Cake作为参数?
这是因为在这种情况下,Java使用静态绑定和动态绑定来选择要调用的方法。
问题所在的行是这样,对吗?
c2.taste(cc);
Run Code Online (Sandbox Code Playgroud)
编译器首先选择要调用的方法(静态绑定)。由于c2是编译时类型的Cake,因此编译器仅看到该taste(Cake)方法。因此它说“打电话taste(Cake)”。
现在,在运行时,运行时需要taste(Cake)根据的运行时类型选择要调用的实现c2。这是动态绑定。它会选择一个Cake吗?还是其中之一ChocolateCake?由于c2是运行时类型ChocolateCake,因此将调用taste(Cake)in 的实现ChocolateCake。
如您所见,您taste(ChocolateCake)甚至没有提到您以为将被称为-的方法!这是因为这是方法的另一种重载taste,并且因为它在ChocolateCake类中,编译器看不到。编译器为什么看不到?因为c2是编译时类型的Cake。
简而言之,编译器决定哪个重载,运行时决定哪个实现。
回应您的陈述:
如果对象是ChocolateCake类型...
只有您知道对象的类型ChocolateCake。编译器没有。它只知道c2类型,Cake因为它的声明就是这样。
由于c2变量的引用类型是具有类型参数Cake的taste方法,因此Cake将被调用。
这是因为Cake类型没有taste采用ChocolateCake实例的方法,因此您不能从Cake类型引用变量中调用该方法。
现在,第二,在Java中,由于运行时多态性的机制,正在调用的重写taste方法,ChocolateCake而不是在父Cake类中声明的版本。这是由于实际上在运行时Cake将检查引用所指向的对象,并taste会调用该特定实例的版本。
因此,由于这两种效果的结合,您可以看到输出。
如果将的引用类型更改为c2,ChocolateCake则会看到输出为:
In taste (ChocolateCake version) of ChocolateCake class
Run Code Online (Sandbox Code Playgroud)
当您调用时c2.taste(cc);,由于现在编译器和运行时都同意taste(ChocolateCake cc)特别调用该方法。
| 归档时间: |
|
| 查看次数: |
397 次 |
| 最近记录: |