2012-07-04 106 views
0

所以,我有這樣的:繼承Java中簡單的澄清

public class A { 

    public int a = 0; 
    public void m(){ 
     System.out.println("A"+a); 
    } 
} 

這:

public class B extends A { 

    public int a = 5 ; 
    public void m(){ 
     System.out.println("B"+a); 
    } 
    public static void main(String[] args) { 
     A oa = new A(); 
     B ob = new B(); 
     A oab = ob; 
     oa.m(); 
     ob.m(); 
     oab.m(); 

     System.out.println("AA"+oa.a); 
     System.out.println("BB"+ob.a); 
     System.out.println("AB"+oab.a); 
    } 
} 

輸出:

A0 
B5 
B5 
AA0 
BB5 
AB0 

我不明白爲什麼oab.m();輸出是B5而不是A0。誰可以給我解釋一下這個?

回答

9

這就是多態性的要點。 oab的具體類型爲B(因爲該對象是使用new B()創建的)。所以調用方法B.m()

看看http://en.wikipedia.org/wiki/Polymorphism_%28computer_science%29中的動物示例,瞭解它爲什麼有用。當你有一隻動物,而這隻動物是一隻貓時,你希望它說「喵!」當你說話時。

+0

方法'米()''中類B'被覆蓋。 'A'類和'B類'對'm()'都有相同的方法簽名。它是被調用的最具體的方法,因爲'oab'是'class B'的一個實例,所以被稱爲'b.m()'。變量'oab'只是被引用爲類型'A'。 – mrswadge

+0

感謝您的回答 – Falco

0
A oa = new A(); 
B ob = new B(); 
A oab = ob; 

從上面的ob代碼是類B的一個實例它可以被存儲在類A的變量作爲A延伸B.但是,隨着所存儲的對象實例是B,因此它是不知道的A的m()函數。 因此,輸出是B5

+0

'oab'意識到有一個函數void void(),因爲類A定義了該函數。但是,由於該函數的實現在類B中被重寫,該類是對象的實際類型,所以它在類B中調用'void m()'的實現。 – nhahtdh

+0

它是nhahtdh。最令我困惑的是我已經把方法** void m()**作爲註釋放在類A中,然後** oab **停止了知道** void m()**。這是有道理的,謝謝 – Falco

0

在繼承中,實際方法調用取決於實際對象的類型而不是引用的類型。

B ob = new B(); 
A oab = ob; 

這裏oabA類型的參考變量,但它指向類型Bob的到對象,以便在運行時oab.m()將從類B

+0

謝謝你的回答 – Falco

+0

@Faico:很高興我可以幫助:) – xyz

1
B ob = new B(); 
A oab = ob; 

類似調用重寫m()方法

A oab=new B(); 

I don't understand why oab.m(); output is B5 instead of A0

因爲你創建的B對象並將其引用到A,使m()被繼承,這就是爲什麼m()B's version被調用。

+0

謝謝你的回答 – Falco

0

在Java中有一些像後期綁定(多態)。這意味着方法的代碼在編譯時(早期綁定)時不是鏈接的,而是在運行時。在調用oab.m();時,JVM正在從aob引用(在您的案例B中)中檢查對象的實際類型(類),並基於該類信息調用該類的方法代碼。這就是爲什麼oab.m();返回B5

您還需要知道後期綁定僅適用於方法,而不適用於字段。對於字段值將由參考類型確定,所以oab.a將返回0而不是5

+0

謝謝你的回答 – Falco

0

假設您有以下:

public class C extends A { 

public int a = 7 ; 
public void m(){ 
    System.out.println("C"+a); 
} 

現在,如果你有這個在你的主要方法...

C oc = new C(); 
A oac = oc; 
oac.m(); 

...你想輸出最後一個電話的東西,對於C類是特定的。

關鍵是B是AC是A,但它們中的每一個都具有A包含的更具體的值版本,並且當您要求這些數據時,應該返回它們的特定版本。

現在你可以這樣做:

// Get an instance of B or C, but you don't 
// care which - could be either: 
A someVersionOfA = getAnInstanceOfA(); 

// This works no matter if you've got an instance 
// of B or C, but the result should vary accordingly: 
someVersionOfA.m(); 

正如別人所說,想到一個爲 「動物」,爲 「貓」 和ç爲 「狗」。如果米()的意思是「製造一些噪音」,然後調用m()應導致「喵」或「Woof!」取決於實例getAnInstanceOfA()返回。

0

您剛剛將B的內部地址複製到A,並將其替換。

B從A繼承,所以沒有編譯問題。

最後,參考所述的被破壞,它現在的參考副本到B