我不了解动态绑定(bind)和适当重写的概念:

这是一些代码:

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使用静态绑定(bind)和动态绑定(bind)来选择要调用的方法。

有问题的行是这个,对吗?

c2.taste(cc);

编译器首先选择要调用的方法(静态绑定(bind))。由于c2的编译时类型为Cake,因此编译器仅看到taste(Cake)方法。因此它说“call taste(Cake)”。

现在,在运行时,运行时需要根据taste(Cake)的运行时类型选择要调用的c2的实现。这是动态绑定(bind)。是否选择Cake中的一个?还是ChocolateCake中的一个?由于c2的运行时类型为ChocolateCake,因此它将在taste(Cake)中调用ChocolateCake的实现。

如您所见,您甚至没有提到您以为会被称为taste(ChocolateCake)的方法!这是因为这是taste方法的不同重载,并且因为它在ChocolateCake类中,编译器看不到。编译器为什么看不到?因为c2具有编译时间,所以请输入Cake

简而言之,编译器决定哪个重载,运行时决定哪个实现。

回应您的陈述:



只有您知道对象的类型是ChocolateCake。编译器没有。它仅知道c2属于Cake类型,因为这就是其声明所说的内容。

07-25 23:51