2012-04-20 240 views
-1

如果Fruit類是超類和水果AppleOrange是子類, 和GoldenDeliciousMacintoshApple子類。繼承和多態衝突

假設如下聲明中給出:

Fruit fruit = new GoldenDelicious(); 
Orange orange = new Orange(); 

回答這個問題解釋

假設方法makeAppleCiderApple類中定義。 fruit可以調用這個方法嗎?橙色可以調用這個方法嗎?

我的答案是:可以 水果調用這個方法嗎?沒有理由沒有明確的投射,必須做明確的投影果實例以啓用Apple類中定義的方法。劑量這個答案是真的嗎?

+3

這看起來極像是一個家庭作業。是嗎? – Jasper 2012-04-20 20:55:34

+0

@Aidanc - 在最後一段的問題末尾有一個建議的解決方案。 – Flexo 2012-04-20 20:59:46

+0

不,我正在從java書的介紹學習java,並且在每章之後解決問題。 所以,我想知道真正的答案,因爲我在對象投射和多態性方面有衝突。 它沒有一個功課。 我正在研究它自學 – MUE 2012-04-20 21:02:48

回答

0

A Fruit沒有makeAppleCider方法的「知識」。 makeAppleCider在子類中定義,不是Fruit的成員。一個類只能訪問它或其父母定義的方法。給定一個特定類型的類,你必須追溯類層次結構來查看你可以訪問哪些方法。你可以將變量的類型想象爲走回類層次結構的起始位置。

如果您希望所有類都有權訪問某個方法,請將其放入層次結構的根目錄中。顯然,使用該方法的邏輯應該是有意義的,否則使用你的代碼的人會感到困惑。

0

另一種選擇當然是使用「接口」 - 一種窮人的多重繼承(但比完全多重繼承更容易理解和實現)。

,你可以,例如,有一個接口八九不離十等(未語法檢查):

public interface CiderFruit { 
    public void makeCider(); 
} 

那麼蘋果可能實現的接口:

public class Apple extends Fruit implements CiderFruit { 
    .... 
    public void makeCider() { 
     doStuff(); 
    } 
    .... 
} 

如果再有一個木瓜類它可以實現相同的界面,可以選擇Apple或Quince,將它投射到CiderFruit(如果不確定它是Apple還是Quince),並調用makeCider()。 (也可以直接調用Apple或Quince類型的引用)。

1

這可以深入到變量的靜態和動態類型中。

Fruit fruit; 

這行聲明靜態類型Fruit可變fruit。這種類型永遠不會改變(它畢竟是靜態的),並且是你通常使用的。

fruit = new GoldenDelicious(); 

這一行是一個分配一個值,該值是一個GoldenDelicious到該變量。變量的動態類型確實會發生變化以反映這種變化。畢竟,變量實際上包含一個GoldenDelicious現在。動態類型是你通常不會使用的東西,但它是當你使用(邪惡)instanceof(並確保在正確的地方調用覆蓋函數)時使用的類型。

現在,你想這樣做:

fruit.makeAppleCider(); 

這是行不通的。在水果中,我們基本上只知道靜態類型,而靜態類型Fruit對這種方法一無所知。 (然而,在幕後,如果GoldenDeliciousMacintosh以不同方式實現的功能,動態類型將確保正確的版本叫做)

正如你在答覆中提到,顯式轉換可以用來改變你正在使用的靜態類型,因此你可以使它以這種方式工作。儘管如此,最好不要這樣做,因爲應該避免演員陣容,而不是「適當的面對面」。

總之,是的,你的回答是正確的。

(是的,我的描述是有些技術性的。我希望你能原諒我這一...)

+0

謝謝,我已經原諒你:)) – MUE 2012-04-20 21:55:10

+0

很好的答案。不同的視角。 – Dhananjay 2012-04-21 09:38:10