2013-04-28 44 views
2

我有點困惑,究竟是如何在Java中創建對象時使用多態性和擴展類等。Java中的多態性和從這些類創建對象

我最近遇到了一個問題,這裏有人幫我解決了問題(請參閱Not able to access object sub class's variable? (Java/Android))以瞭解背景。

我試圖創建像這樣的物體:

Quad hero = new Hero(); 

凡英雄是四的子類();

我有我的英雄類中的變量,我不是以上訪問。

的解決方案是我的對象創建更改爲:

Hero hero = new Hero(); 

這樣一來,通過我的英雄對象,我能夠訪問我的兩個Quad和英雄類的所有方法和變量。

我現在的問題是 - 這是爲什麼?

而且考慮到這一點,當會是用我原始的方法有用:

Quad hero = new Hero(); 

那一個對我來說很有意義的英雄也是四。我已經多次在Java代碼示例中看到過這種類型的聲明,並認爲我理解,但最近的事件已經證明不是。

將不勝感激,如果有人可以解釋這對我來說 - 感謝

回答

2

聲明的變量類型爲Quad,意味着變量也可以參考其他類型的Quad子類,不僅Hero。如果你通過這個參考,接收機只會知道它是「某種四元組」,不能依靠它作爲Hero。因此,它不能訪問僅在子類中聲明的引用字段。

至於何時使用這種類型的賦值,我通常只在使用接口類型時才這樣做。像:

public List<SomeObject> doSomething() { 
    List<SomeObject> result = new ArrayList<>(); 
    // do something 
    return result; 
} 

但它確實只是一種習慣。

4

假設OtherHero也從Quad與不同行爲的子類:

這將很好地工作:

Quad hero = new Hero(); 
// some code 
hero = new OtherHero(); 

而下面將無法編譯:

Hero hero = new Hero(); 
// some code 
hero = new OtherHero(); 

這沒有按」 t似乎是有用的。現在假設你有一個方法,它有Quad作爲返回類型。我將在僞代碼寫:

Quad method() { 
    if (condition) 
     return new Hero(); 
    else 
     return new OtherHero(); 
} 

所以,你居然不知道它是否會返回一個HeroOtherHero

現在,你可以這樣寫:

Quad foo = method(); 

現在,您實際上不知道foo的確切類型,但您可以將它用作Quad

一個流行的例子是java.util.List

你可以寫:

List<Integer> list = Arrays.asList(1,2,3,4,5,6); 
Collections.shuffle(list); 

List是一個接口,通過ArrayListLinkedList和許多其他類實現的。在不知道代碼的情況下,我們不知道Arrays.asList()返回的是哪一類,但我們可以將它用作List

+0

嗯......有趣@jlordo,謝謝。所以如果我舉個例子,敵人1,敵人2,敵人3和英雄,都是以四邊形的形式創造出來的,並且想將它們組合成一個陣列,那麼我就可以像他們所有的四邊形一樣?但是,我將如何訪問僅存儲在子類中的變量? (比如說Hero子類有一個存儲在其中的變量,Enemy類沒有。我如何訪問這些變量,因爲它們不在基類中?我不能通過對象訪問它們,而不改變它們這是類型英雄,但我不能與敵人分組嗎?謝謝!! – Zippy 2013-04-28 22:53:32

+0

@Zippy:這取決於你如何訪問這些變量,以及你想要與他們做什麼。如果先查看'instanceof'運算符,則可以安全地投射。我寧願製作一個'Quad'接口(或抽象類),只使用它的方法。無論如何,變量應該被封裝,所以你可以通過類中的方法訪問它們。 – jlordo 2013-04-29 01:48:15

+0

謝謝@jlordo - 我可以請你編輯你的答案,舉一個你上面評論的例子嗎? (關於如何訪問變量,正如我在評論中所描述的那樣?我通常通過示例的方式發現它更容易理解) - 然後我將閱讀並標記您的答案 - 再次感謝,非常感謝! – Zippy 2013-04-29 18:34:05

2

如果將對象存儲在變量Quad中,那麼對於所有編譯器都知道,存儲在該變量中的對象是Quad,僅此而已。它可能是一個子類型,當然,但編譯器不知道該子類型是什麼。衆所周知,該子類型將向基類型引入絕對零成員。如果編譯器不能保證該對象比Quad更多,那麼它不會允許您做任何事情,而不僅僅是允許您使用Quad做什麼。

授予,可以看到,這個變量只有一個new Hero()表達式。並且,您可以知道,某個特定變量只能保存Hero類型的對象。但這是您可以在實踐中推斷的運行時信息。編譯器無法計算所有這些場景。這就是爲什麼它有你。如果你知道存儲在該變量中的對象總是類型Hero,你可以繼續並將其表達給編譯器。

語言允許您將對象轉換爲超類型的一個原因是因爲在很多情況下,您希望將該對象傳遞給不必知道基類的所有可能子類型的方法(比如說,Hero),但僅限於傳入的對象至少是基類(例如,Quad)。另一個典型的場景是,當你想存儲不是全部相同特定類型的各種物體(它們並不全是Hero),但它們都有一個共同的祖先(它們都是Quad),並且你想對它們做些什麼,統稱。一般來說,將對象轉換爲祖先類是允許的,因爲在需要該基類型的情況下,使對象與其基本類型兼容非常有用。