2017-08-29 44 views
0

對於標題感到抱歉,我無法更好地用一句話解釋它!java中的泛型的雙向耦合

所以這裏的問題是,我做在Java中的小紙牌遊戲引擎,我想定義接口的遊戲要儘可能地通用

,所以我有這些接口

public interface Card 
{ 
    //some methods 
} 
public interface CardGame<TCard extends Card,TPlayer extends Player> 
{ 
    //example method 
    TPlayer getPlayerByName(String name); 
} 
public interface Player<TCardGame extends CardGame> 
{ 
    //HERE IS THE ISSUE 
    List<TCard> getCards(); 
} 

的問題是在過去的界面,我想迫使玩家返還相同種類的遊戲,是卡他是一個普通的

換句話說

Player<BannaCardGame>,應該有List<BananCards>

,但我無法找到正確的語法要做到這一點,TCard播放器界面中已經沒有意義

所以我怎麼能實現這種行爲?

+1

首先,不要使用原始類型。 – shmosel

+0

你確定要保持對你自我的神祕感:P,我不確定我在追隨,但是感謝評論 –

+0

'TCardGame擴展CardGame'使用raw(=未參數化)類型'CardGame'。不要這樣做,這是不安全的。 – shmosel

回答

1

首先,你可能想重新考慮你是否真的需要這個。但是不知道爲什麼,你可能需要等這裏的你如何能解決你的問題的一些建議:

不要把PlayerCardGame但配合既Card

public interface Card {} 

public interface CardGame<TCard extends Card,TPlayer extends Player<TCard>> { 
//example method 
TPlayer getPlayerByName(String name); 
} 

public interface Player<TCard extends Card> {  
List<TCard> getCards(); 
} 

現在,你只允許定義使用PlayerCard的匹配實現的CardGame。但是,我不確定設計是否好(爲什麼玩家實例要依賴於卡的類型?),但是由於我們不知道你的需求以及你爲什麼決定這樣設計,所以很難在這方面給予很多建議(而且它可能超出了SO的範圍),所以我會留給你。

編輯:

從您的意見,似乎你也想加入getGame()Player接口(注:對於未來的問題:補充一點,這個問題爲好,否則可能會丟失)。

你可以這樣定義該方法(我將包括完整的接口):

public interface Player<TCard extends Card> {  
    List<TCard> getCards(); 

    CardGame<TCard, ? extends Player<TCard>> getGame(); 
} 

這意味着玩家可以返回(屬於哪一種?),使用權類型卡的所有遊戲以及爲該類型的卡申報的任何類型的玩家。

如果您想進一步限制這個,你可以擴展你的接口(也許這就是你究竟是什麼後):然後

//for the changes on TPlayer see the comment on Player 
public interface CardGame<TCard extends Card,TPlayer extends Player<TCard, TPlayer>> { 
    //example method 
    TPlayer getPlayerByName(String name); 
} 

//Require the implementations to register themselves as generic types 
public interface Player<TCard extends Card, TPlayer extends Player<TCard, TPlayer>> {  
    List<TCard> getCards(); 

    CardGame<TCard, TPlayer> getGame(); 
} 

一個BananaCard遊戲看起來是這樣的:

class BananaPlayer implements Player<BananaCard, BananaPlayer> { 
    public List<BananaCard> getCards() { /*snip*/ } 

    public CardGame<BananaCard, BananaPlayer> getGame() { /*snip*/ } 
} 

class BananaGame implements CardGame<BananaCard, BananaPlayer> { 
    public BananaPlayer getPlayerByName(String pName) { /*snip*/ }  
} 
+0

我正在考慮設計部分 最初沒有任何東西是通用的,但是越深入,越糟糕,玩家應該擁有強大的遊戲類型,而不僅僅是CardGame,所以我最終重寫了每個子類中的getGame方法以返回相同的類型!這在c#中是不允許的,例如,所以我追溯並開始使用泛型 至於另一個我同意的問題,這就是爲什麼一個玩家是其遊戲的一般性而不是我設計中的卡,但是我怎麼能在玩家上強制該遊戲的卡的類型! –

+0

我不確定我是否理解你最後一句話(一個問題?),但你可以這樣做:'BananaCard extends Card','BananaPlayer extends Player ','BananaCardGame extends CardGame '''' '不會被允許)。 – Thomas

+0

我試過這個,我的意思是最明顯的方法是在播放器定義中包含卡的通用名稱,但正如你所說,這看起來很糟糕和混亂,玩家不應該被綁定到卡的定義,它應該被綁定到遊戲的定義,並在同一時間,該遊戲是一個通用的卡,但我不能使用該卡在播放器界面上下文 –