2013-01-09 130 views
2

爲了從概念上理解繼承,接口&多態,我創建了幾個類來測試事情。我得到的結果不是我期望的結果。代碼如下:Java接口與繼承和多態

public class Animal implements Comparable{ 
//Animal constructor & methods 
public int compareTo(Object arg0){System.out.println("Animal.compareTo");} 
} 

public class Bear extends Animal{ 
//Bear constructor & methods 
} 

public class PolarBear extends Bear implements Comparable{ 
//PolarBear constructor & methods 
public int compareTo(Object arg0) {System.out.println("PolarBear.compareTo"); 

我沒有得到任何錯誤,說我不能再次實現Comparable。但在我的測試中,一旦創建PolarBear,即使PolarBear應該繼承Animal的compareTo,我也無法回到Animal的compareTo方法。我測試了以下:

Animal bobo = new PolarBear(); 
bobo.compareTo(null); 
((PolarBear) bobo).compareTo(null); 
((Animal)bobo).compareTo(null); 
((Comparable) bobo).compareTo(null);  

而且他們每個人的印刷:

PolarBear.compareTo 

有什麼辦法來訪問AnimalcompareTo?從邏輯上講,我不希望能夠比較PolarBear以及PolarBear質量的動物質量嗎?

+1

您可以隨時從子類中調用'super.compareTo()'。 – assylias

+1

這些方法是動態綁定到實例的。 'bobo'是一個'PolarBear',因此總是調用'PolarBear'的'compareTo(...)'方法。爲什麼你想要別的東西被稱爲? – MrSmith42

+2

順便說一下,應該是'implements Comparable ' – fge

回答

7

不要緊,你是您鑄造bobo對象PolarBearAnimal,或Comparable,物體的運行時類型將永遠是PolarBear因爲你實例化它作爲

Animal bobo = new PolarBear(); 

因此每當你打電話.compareTo(wtv)它會調用PolarBear實現。

這是什麼多態性。閱讀late binding,這是java中如何實現polymorphishm。

如果您想調用父類的compareTo(wtv)方法,那麼您必須在其他子類的方法內執行super.compareTo(wtv)

+0

該方法需要具有super.compareTo? 如果我想要有2個compareTo方法,一個在Animal中,一個在PolarBear中比較不同的東西呢? 不會把super.compareTo放在PolarBear.compareTo的方法體中會失去這個目的嗎? – user1901074

+0

這取決於。由於您重寫了'PolarBear'中的方法,因此您通過調用'super.compareTo'從父類中擴展功能。你不必這樣做。你將無法直接從'PolarBear'實例訪問'Animal'的compareTo。 –

+2

@ user1901074 - 大多數處理java庫中比較的地方都允許您提供一個Comparator類,它可以比較對象,而不依賴於可比較的對象。這通常是你如何處理有幾個比較實現的場景。 – radai

1

您可以隨時從您的PolarBear中調用super.compareTo(arg0)來調用放置在Animal.compareTo中的邏輯。

+0

你只能在對象中使用super。你正在做一個主函數(這是一個靜態函數,不屬於任何對象)。您必須將超級通話**放入您的PolarBear的compareTo方法 – Claudio

2

compareTo和inheritence通常是tricky business。從理論上講,具有可比較具體超類的子類打破了可比契約。例如 - 假設我有一個超類A,它通過檢查字段a1和a1與其他A進行比較。現在讓我們添加一個具有額外字段b1的子類B. anA.compareTo(aB)將通過A1和A2時比較((A)aB).compareTo(anA)不會做同樣的
爲你的問題 - 你只能從子類調用自身的compareTo的動物版本,通過執行類似

super.compareTo(<something>) 

而不是從「外部「,因爲你已經覆蓋了該方法。你有責任與外界保持同樣的「合同」,就像你剛剛被覆蓋的方法一樣。

0

這很簡單。底層對象是PolarBear類,並且您每次都更改對象的接口(用於保存對象引用的類)。

JVM在編譯時檢查接口中的方法(用於存放對象引用的類)是否存在,但綁定發生在運行時,因爲Child(PolearBear)具有該方法,所以它將始終運行它。

使用super.compareTo()爲了調用父方法。