2017-02-27 44 views
0

在講座中,我們展示了這段代碼,並告訴它創建了雙重調度,但爲什麼它不會創建無限循環?爲什麼不是Java雙重調度造成的死循環?

如果c3po.greet(c4po);從TranslationRobot調用TranslationRobot方法

爲什麼c5po.greet(c4po);調用CarrierRobot中的AbstractRobot方法而不是TranslationRobot方法,然後不調用TranslationRobot中的AbstractRobot方法,然後調用CarrierRobot中的抽象方法等等?

什麼決定它是否調用AbstractRobot方法?

AbstractRobot.java

abstract class AbstractRobot extends Robot { 
abstract void greet(AbstractRobot other); 
abstract void greet(TranslationRobot other); 
abstract void greet(CarrierRobot other); 
} 

CarrierRobot.Java

class CarrierRobot extends AbstractRobot { 
... 
void greet(TranslationRobot other) { 
    talk("'Hello from a TranslationRobot to a CarrierRobot.'"); } 
void greet(CarrierRobot other) { 
    talk("'Hello from a CarrierRobot to another.'"); } 
void greet(AbstractRobot other) { 
    other.greet(this); 
}} 

TranslationRobot.Java

public class TranslationRobot extends AbstractRobot { 
... 
void greet(TranslationRobot other) { 
    talk("'Hello from a TranslationRobot to another.'"); } 
void greet(CarrierRobot other) { 
    talk("'Hello from a CarrierRobot to a TranslationRobot.'"); } 
void greet(AbstractRobot other) { 
    other.greet(this); 
} } 

DispatchWorld.Java

class DispatchWorld { 
public static void main (String[] args) { 
AbstractRobot c3po = new TranslationRobot(); 
AbstractRobot c4po = new TranslationRobot(); 
AbstractRobot c5po = new CarrierRobot(); 
AbstractRobot c6po = new CarrierRobot(); 
c3po.greet(c4po); 
c5po.greet(c4po); 
c4po.greet(c5po); 
c5po.greet(c6po); 
} } 

這將產生輸出:

Standard Model says 'Hello from a TranslationRobot to another.' 
Standard Model says 'Hello from a CarrierRobot to a TranslationRobot.' 
Standard Model says 'Hello from a TranslationRobot to a CarrierRobot.' 
Standard Model says 'Hello from a CarrierRobot to another.' 
+2

可能重複[Java方法重載+雙重調度](http://stackoverflow.com/questions/2794195/java-method-overloading-double-dispatch) –

+0

方法名重載之間的選擇是在編譯時進行的時間,基於方法參數的* static *類型。這也許是在Java中實現雙重調度時最重要的一點。 –

+0

我不同意這是一個重複的問題,另一個有一個父類,該方法被調用並詢問爲什麼'這個'是指父母而不是孩子。而我在這裏問爲什麼在同一個類中爲另一個方法選擇一個方法,爲什麼這個參數是抽象的或具體的 –

回答

0

我覺得爲什麼這個工程及答案爲什麼沒有無限遞歸可能,如果我們通過刪除所有方法重載,並把明確不同的名稱,而不是有點重構代碼所示更好:

abstract class Robot 
{ 
    void talk(String msg) 
    { 
     System.out.println(msg); 
    } 
} 

abstract class AbstractRobot extends Robot 
{ 
    abstract void greet(AbstractRobot other); 

    abstract void greetFromTranslationRobot(TranslationRobot other); 

    abstract void greetFromCarrierRobot(CarrierRobot other); 
} 

class CarrierRobot extends AbstractRobot 
{ 
    void greetFromTranslationRobot(TranslationRobot other) 
    { 
     talk("'Hello from a TranslationRobot to a CarrierRobot.'"); 
    } 

    void greetFromCarrierRobot(CarrierRobot other) 
    { 
     talk("'Hello from a CarrierRobot to another.'"); 
    } 

    void greet(AbstractRobot other) 
    { 
     other.greetFromCarrierRobot(this); 
    } 
} 


public class TranslationRobot extends AbstractRobot 
{ 
    void greetFromTranslationRobot(TranslationRobot other) 
    { 
     talk("'Hello from a TranslationRobot to another.'"); 
    } 

    void greetFromCarrierRobot(CarrierRobot other) 
    { 
     talk("'Hello from a CarrierRobot to a TranslationRobot.'"); 
    } 

    void greet(AbstractRobot other) 
    { 
     other.greetFromTranslationRobot(this); 
    } 
} 

從視圖方法void greet(AbstractRobot other)void greet(TranslationRobot other)void greet(CarrierRobot other)編譯器的點是3種明顯不同的方法,這我改名只是凸顯。

所以像c3po.greet(c4po)呼叫實際上是TranslationRobot.greet通話將其轉發到other.greetFromTranslationRobot(this)這是TranslationRobot.greetFromTranslationRobot而這顯然不應導致任何無限遞歸。