开发者

Generic class of generic class in Java

开发者 https://www.devze.com 2022-12-20 21:43 出处:网络
I had a开发者_如何学C class hierarchy setup like so: public abstract class GameController public abstract class Game

I had a开发者_如何学C class hierarchy setup like so:

public abstract class GameController
public abstract class Game

I wanted to use a generic GameController class so it takes specific Game subclasses, so I changed it to:

public abstract class GameController<GameType extends Game>
public abstract class Game

But then I also wanted to have a generic Game to take specific player subclasses, so I changed it to:

public abstract class GameController<GameType extends Game<PlayerType>, PlayerType extends Player>
public abstract class Game<PlayerType extends Player>

Is there a better way to lay this out so I don't have to declare PlayerType twice (in both the GameController subclass and the Game subclass)?

Edit:

GameController is a network class, it receives post and get requests, and translates them into something closer to what a game needs, then a subclass, say MyGameController, further translates the byte[] that was posted into a method call for a specific game class, say MyGame. Code sample:

GameController:

public abstract class GameController<GameType extends Game<PlayerType>, PlayerType extends Player> {
    private Hashtable<String, GameType> games;
    public MultiplayerMain() {
        super();
        games = new Hashtable<String, GameType>();
    }
    protected abstract GameType createGame(InputStream in, String gameId);
    protected abstract PlayerType createPlayer(InputStream in, GameType game, String playerId);
    protected abstract byte[] gameAction(InputStream in, GameType game, PlayerType player);

    //Other stuff that calls createGame, createPlayer, and gameAction
}

Game:

public abstract class Game<PlayerType extends Player> {
    private Hashtable <String, PlayerType> players = new Hashtable<String, PlayerType>();
    public final String gameId;
    public Game (String id) {
        gameId = id;
    }
    public abstract byte[] getGameState();
    public abstract byte[] getGameState(PlayerType player);
    final PlayerType getPlayer(String userId) {
        return players.get(userId);
    }
    final void addPlayer(PlayerType player) {
        players.put(player.userId,player);
        playerAdded(player);
    }
    final void removePlayer(PlayerType player) {
        players.remove(player);
        playerRemoved(player);
    }
    protected void playerAdded(PlayerType player) {}
    protected void playerRemoved(PlayerType player) {}
}

MyGameController:

public class MyGameController extends GameController<MyGame,MyPlaer> {
    protected MyGame createGame(InputStream in, String gameId) {
        byte[] data = getInitializationData(in);
        return new MyGame(gameId,data);
    }

    protected byte[] gameAction(InputStream in, MyGame game, Player player) {
        byte[] data = getData(in);
        MyGame.methodSpecificToMyGameClassBasedOnInputStream(data);
        return game.getGameState(player);
    }

    protected Player createPlayer(InputStream in, MyGame game, String playerId) {
        byte[] otherData = getOtherData(in,game)
        return new MyPlayer(playerId,otherData);
    }
}

MyGame:

public class MyGame extends Game<MyPlayer> {

    public MyGame(String id) {
        //...
    }

    public byte[] getGameState() {
        //...
    }

    public byte[] getGameState(Player user) {
        //...
    }

    public void methodSpecificToMyGameClassBasedOnInputStream(byte[] data) {
        //...
    }
}


Do you need generics for this? Instead, can you inject Player into Game and Game into GameController?

public class Game {
    private final PlayerType playerType;

    public Game(PlayerType playerType) {...}

}

public class GameController {
    private final Game game;

    public GameController(Game game) {...}
}


It seems like you're really tightly coupling the definition of GameController to the inheritance hierarchy of Game and GameType; similarly with Game to Player and PlayerType. I would encourage you to couple that relationship significantly more loosely; composition, as other posters are suggesting, is almost certainly the right way to go here, since you're describing as "has-a" relationship.


I'm not sure that you need to define PlayerType in you game controller. You can probably just do the following:

public abstract class GameController<GameType extends Game<?>>
public abstract class Game<PlayerType extends Player>

gameController.getPlayer() could only return a Player, but you could still use gameController.getGame().getPlayer() which would return a PlayerType.

Edit: Based on the method signatures you have provided, no, I don't see a way to declare the generic types without declaring PlayerType twice.

I agree with the others who say your model is too coupled. It feels like gameAction shouldn't care what type of Game or Player it takes.

0

精彩评论

暂无评论...
验证码 换一张
取 消