簡體   English   中英

不清楚動態綁定

[英]Unclear about dynamic binding

我不理解動態綁定和覆蓋的概念:

這是一些代碼:

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是編譯時類型Cake ,編譯器只能看到taste(Cake)方法。 所以它說“叫taste(Cake) ”。

現在,在運行時,運行時需要根據c2的運行時類型選擇要調用的taste(Cake)實現。 這是動態綁定。 它選擇Cake那個嗎? 還是ChocolateCake那個? 由於c2屬於運行時類型ChocolateCake ,因此它在ChocolateCake調用taste(Cake)的實現。

正如你所看到的,你認為可以稱之為的方法 - taste(ChocolateCake) - 甚至沒有提到! 這是因為這是taste方法的不同重載,因為它在ChocolateCake類中,編譯器無法看到。 為什么編譯器看不到? 因為c2是編譯時類型Cake

簡而言之,編譯器決定哪個重載,運行時決定哪個實現。

回應你的陳述:

如果對象是ChocolateCake類型...

只有知道該對象是ChocolateCake類型。 編譯器沒有。 它只知道c2Cake類型,因為這就是它的聲明所說的。

由於c2變量的引用類型是Cake ,因此將調用具有Cake類型參數的taste方法。

這是因為Cake類型沒有帶有ChocolateCake實例的taste方法,因此您無法從Cake類型引用變量調用該方法。

其次,在Java中,由於運行時多態性的機制,正在調用ChocolateCake的重寫taste方法,而不是在父類Cake聲明的版本。 這是因為在運行時事實上將會檢查Cake引用所指向的對象,並且將調用該特定實例的taste版本。

因此,由於這兩種效果的結合,您可以看到輸出。

如果將c2的引用類型更改為ChocolateCake您會看到輸出為:

In taste (ChocolateCake version) of ChocolateCake class 

當你調用c2.taste(cc); 因為現在編譯器和運行時都同意特別調用那種taste(ChocolateCake cc)方法。

在Java中,在c2.taste(cc)情況下決定調用哪個方法集是在編譯時基於c2的編譯時類型執行的。 c2的編譯時類型是Cake ,這意味着對c2 任何方法調用c2搜索Cake及其超類,並且不搜索Cake任何子類(即ChocolateCake ),即使所有子類對編譯器都可見。

在運行時基於接收器和參數的實際運行時類型執行完全動態方法解析的語言,這將使c2.taste(cc)被解析為ChocolateCake.taste(ChocolateCake cc) ,這種情況很少見,因為它會對運行時性能產生負面影響。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM