簡體   English   中英

循環泛型

[英]cyclical generics

我正在嘗試采取以下措施:

public interface Player<R>
{
    R takeTurn(Game game);
}

public interface Game
{
}

public class XPlayer
    implements Player<Interger>
{
    // XGame won't work because the interface takes Game
    public Integer takeTurn(final XGame game)
    {
        return (null);
    }
}

public class XGame
{
}

我要堅持的是我需要在Game和Player界面中進行哪些更改才能使仿制葯正常工作(我停頓了一下,但我的頭上還有些毛毛:-)特別是我掛在Player需要處理的地方知道游戲的類型,並且游戲需要知道玩家的類型。

這不是一個泛型問題(未鍵入Game )。

這是一個繼承問題。 嘗試這個:

public class XGame implements Game // added interface

因此,在這種情況下,我們會有游戲和玩家,而這些游戲和玩家可能會被細分。 TicTacToe游戲使用TicTacToe PLAYERS,反之亦然。

為此,將所有類放入聲明中。 該聲明非常丑陋,但是使用它的代碼卻非常干凈。

我喜歡在所使用的類系統中按相同順序保留泛型類型的列表。

abstract class Game<//
        G extends Game<G, P>, //
        P extends Player<G, P>> {
    P getCurrentPlayer() {return null;}
}

abstract class Player<//
        G extends Game<G, P>, //
        P extends Player<G, P>> {
    G getCurrentGame() {return null;
}

您可以像這樣使用這些抽象類:

class TTTGame extends Game<TTTGame, TTTPlayer> {}

class TTTPlayer extends Player<TTTGame, TTTPlayer> {}

class ChessGame extends Game<ChessGame, ChessPlayer> {}

class ChessPlayer extends Player<ChessGame, ChessPlayer> {}

等等。 強類型表示在所有返回類型,參數和可見字段中,國際象棋玩家的游戲將是國際象棋,而國際象棋游戲的玩家將是國際象棋。

您甚至可以做一些技巧,例如以一種方式擴展繼承層次結構,而不是另一種方式。 假設我們定義了一類游戲,其中玩家唯一的動作就是擲硬幣並報告正面或反面。 我們可以創建一個可用於任何投幣游戲的投幣游戲機,以及一個類型仍為通用但綁定了P的投幣游戲。

class CoinGame<G extends CoinGame<G>> //
        extends Game<G, CoinPlayer<G>> {
}

class CoinPlayer<G extends CoinGame<G>> //
        extends Player<G, CoinPlayer<G>> {
    boolean flip() {
        return true;
    };
}

投幣游戲的子類只有一個類型參數,因為它們都接受投幣游戲類型的玩家。 大多數具體游戲都會將此參數綁定到自身:

class DontFlipHeads //
        extends CoinGame<DontFlipHeads> {
    class YouLose extends Exception {
    }

    void turn() throws YouLose {
        if (getCurrentPlayer().flip()) throw new YouLose();
    }
}

DontFlipHeads類知道其播放器具有flip方法,因為即使在繼承層次結構的底部通常定義了getCurrentPlayer(),它也會擴展已綁定具有該方法的播放器類型的游戲。

請注意,DontFlipHeads的播放器類需要具有一個參數。 從而:

…
DontFlipHeads game = new DontFlipHeads();
CoinPlayer<DontFlipHeads> player1 = new CoinPlayer<DontFlipHeads>();

game.addPlayer(player1, 1);

如果沒有這種雙向引用,則沒有必要。 但由於引用存在 ,你可以

DontFlipHeads whatGame = player1.getGame();

沒有任何鑄造。

為什么沒有這樣的東西-

    public Integer takeTurn(Game game)
      {
         XGame xGame = (XGame) game; // assuming XGame implements Game  
         return ...;
      }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM