2015-05-07 72 views
2

一個非常神祕的多態性問題:動態方法綁定異常?

import static java.lang.System.* 
class Super{ 
    public void meth(Super other){ 
     out.println("#1 - in Super.meth(Super)"); 
    } 
} 

class Sub extends Super{ 
    public void meth(Super other){ 
     out.println("#2 - in Sub.meth(Super)"); 
    } 
    public void meth(Sub other){ 
     out.println("#3 - in Sub.meth(Sub)"); 
    } 
} 

public class MethodTest{ 
    public static void main(String[] args){ 
    Super sup = new Super(); 
    Sub sub = new Sub(); 
    Super sup_ref_sub = new Sub(); 

    sup_ref_sub.meth(sub); 
    } 
} 

有了上面的代碼,我的輸出是「#2 - in Sub.meth(Super)」,而我所期待的「#3 - in Sub.meth(Sub)」,更奇怪的是,當我註釋掉<public void meth(Super other){...}>,輸出改爲「#1 - in Super.meth(Super) 」。

回答

0

雖然sup_ref_sub實際上是Sub,因爲它聲明爲Super它的行爲如同Super

Super只有public void meth(Super)作爲其唯一的方法;因此爲什麼#2和#3打印在您的測試中。

要得到#3印刷申報sup_ref_subSub

0

你在一兩件事,實際類型的對象將被用來確定方法被調用是正確的所以在這種情況下,我們有兩種選擇:

public void meth(Super other) 
public void meth(Sub other) 

在Java中,動態方法分派只發生在調用方法的對象上,而不是用於重載方法的參數類型。 現在,作爲每了Java文檔:

當調用一個方法(§15.12)中,使用的實際參數( 任何顯式的類型參數和)編譯時間類型的 參數的數目和在編譯時,確定將調用(§15.12.2)的方法的簽名。如果調用 的方法是實例方法,則使用動態方法查找(第15.12.4節),將在運行時確定要調用的實際方法爲 。

而現在編譯類型的類型是Super,所以調用的方法將是public void meth(Super other)。 SO線路輸出:

Super sup_ref_sub = new Sub(); 
sup_ref_sub.meth(sub); 

將是#2 - in Sub.meth(Super)