2016-08-27 36 views
2

由於參數是靜態的,我在嘗試將參數傳遞給父類泛型類的構造函數時出現問題,因此我必須在編譯時顯式指定類型。傳遞靜態字段爲通用類型

這裏有兩類問題:

public class CardStack<T extends Card> extends ArrayList<T> 

public class Deck<T extends Card> extends CardStack<T> 

我之所以需要「T擴展卡」並不僅僅是卡是因爲我共享客戶端之間的這些類(這需要使它們)和一個服務器(它只關心值)。

我靜態地創建了一副單卡,在放入每個卡組後將被洗牌。

private static final CardStack<Card> NEW_DECK; 
static { 
    NEW_DECK = new CardStack<>(DECK_SIZE); 
    for (int i = 0; i < DECK_SIZE; i++) { 
     NEW_DECK.push(new Card(Card.Suit.values()[i/Card.CARD_VALUE_MAX], 
      i % Card.CARD_VALUE_MAX + 1)); 
    } 
} 

構造甲板:

public Deck() { 
    super(NEW_DECK); // Error Here 
    Collections.shuffle(this); 
} 

構造CardStack:

protected CardStack(final CardStack<? extends T> cardStack) { 
    super(cardStack); 
} 

我無法找出把什麼 「擴展T'」。我已經嘗試了一些組合,但似乎沒有任何工作,所以似乎我不完全理解發生了什麼。這種設計可能嗎?如果不是更好的解決方案。謝謝!

============================================== ===========================

編輯:更好地解釋使用泛型的推理。

首先,我想在上面說過的客戶端和服務器之間共享這些類。真正的問題是當我試圖擴展這些類來呈現它們時。所有客戶端類都包含渲染信息和方法(x/y座標,繪製和檢測點擊的方法)。

這工作正常我ClientCard extends Card類,但是當我試圖讓ClientCardStack extends CardStack因爲CardStack包含卡的問題出現了,我無法使它們,因爲它們不包含正確的信息,而我真正需要的是ClientCardStack extends CardStack<ClientCard>導致所有這些問題。

+0

如果我創建一個'class MyCard extends Card {}'然後創建一個'Deck ',當我的構造函數填充'Card'後,當我嘗試從它獲取一個'MyCard'時會發生什麼?我懷疑你誤解了某些東西,但你對爲什麼認爲需要泛型的解釋並不能說明誤解是什麼。我同意答案,表明你可能不應該在這裏使用泛型。或者至少,泛型使設計複雜化。傳遞'NEW_DECK'就像你試圖做的*永遠不會*工作。您需要使用類似抽象工廠方法的東西。 – Radiodef

+0

謝謝,我現在明白爲什麼它目前不能工作,但我想知道我的方法是否仍然有效。我已經更新了使用泛型的理由。 – Kelvin

回答

2

問題是NEW_DECK的類型是CardStack<Card>,而您要調用的超級構造函數需要CardStack<? extends T>T並不總是成爲Card的超類。

對此的最佳解決方案實際上不使用泛型。繼承規定,無論您是客戶端版本還是服務器版本的實例,您仍然有一個Card的實例,所以當您不知道您是在客戶端還是服務器上時,只需使用Card即可。

+0

但是在CardStack中,我指定'T extends Card',所以在構造函數中當我說'?延伸T'它應該暗示'?延長T延長卡,這就是爲什麼我覺得它應該工作。 – Kelvin

+0

考慮它與固定類型:你不能通過'CardStack '作爲'CardStack <?擴展CardClient>'因爲'Card'不擴展'CardClient'。 – RamenChef

0

讓我們檢查Deck構造:

public Deck() { 
    super(NEW_DECK); // supposed to invoke CardStack<T> 
    Collections.shuffle(this); 
} 

那麼,我們有什麼在NEW_DECK

private static final CardStack<Card> NEW_DECK; 

的一點是,這<Card>不是<T>

private static final CardStack<T> NEW_DECK; 
// Warning: Cannot make a static reference to a non-static type 

想像一下來電:

Deck<Card2> deck = new Deck(); 

deck -s左手類型是Deck<Card2>和右手型,如果你嘗試將通配符添加到NEW_DECK它會更明顯是Deck<Card>。直觀地說,它應該是正確的。不幸的是,Java的泛型不是不變的。它代替了invariant。即Deck<Card2>不是Deck<Card>的子類型。

您需要在構造函數中顯式定義類型。例如: -

public static final CardStack<Card> NEW_DECK; // public now 

public Deck() { // creates an empty deck 
    super(16); 
} 

public Deck(CardStack<T> stack) { 
    super(stack); 
    Collections.shuffle(this); 
} 

您可以調用第二個構造是這樣的:

public static void main(String[] args) { 
    Deck<Card> deck = new Deck(NEW_DECK); 
} 

我相信這些變化將改變你的設計一點點。但他們做得很好!他們強迫你做某種dependency injection