如何继承Cyclic Generics?

时间:2011-05-02 21:20:18

标签: java generics

我正在为棋盘游戏平台创建一个小框架,我创建了以下界面,以便尽可能通用我将在此框架中放置的游戏。

我想使用Java Generics,这样每个实现都不仅如此 以适当的OO方式实现各自的接口,但也具有特定于游戏的要求的特定具体类可访问和强类型(没有强制转换等)。

例如,CheckersPlayer会延伸PlayerCheckersPlayerImpl实施CheckersPlayer},CheckersGame会延伸GameCheckersGameImpl 1}}实施CheckersGame)和CheckersGameTable扩展GameTable等。

public interface Player
{
...
}

public Game<T extends GameTable, P extends Player>
{
...
   public T getTable();

   public List<P> getPlayers();
} 

public interface GameFactory<T extends GameTable, P extends Player, G extends Game>
{
   public G getGameInstance(T table, List<P> players)
} 

public interface GameTable<P extends Player, G extends Game, GF extends GameFactory>
{
...
   public G getCurrentGame();

   public List<P> getPlayers();
}

关于这一点的好处是,例如CheckersGame将被声明为:

   public interface CheckersGame extends Game<CheckersTable, CheckersPlayer>
   {
     public CheckersTable getTable();

     public List<CheckersPlayer> getPlayers();
   }

到目前为止一切顺利。

每个GameTable实际上有很多共同之处,我选择使用模板模式将一些常见的算法逻辑放在一个抽象实现中,然后扩展它的相应具体类就会“填写”空白与特定游戏的东西。

然而,现在我的Generics内容中出现了各种各样的“边界”错误。

我的AbstractTable声明如下:

public abstract class AbstractTable<P extends Player, G extends Game, GF extends GameFactory> implements GameTable<P,G,GF>
{      
  GF gameFactory; 

  ...
  public final void startGame()
  {
    //the following line does not work
    G newGame = gameFactory.getGameInstance(this, getPlayers());
  }

}

由于某种原因,带有工厂方法的行不起作用,并返回Game而不是G。 所以我尝试更改类声明,以更具体地说明GameFactory通用类型的类型:

  public abstract class AbstractTable<P extends Player, G extends Game, GF extends GameFactory<? extends GameTable, P, G> 
        implements GameTable<P,G,GF>

但是现在我传递的类型(AbstractTable<P,G,GF>)和期望的类型? extends GameTable之间存在类型不匹配。

所以我也尝试按如下方式修改工厂:

public interface GameFactory<T extends GameTable<P, G, ? extends GameFactory>, P extends Player, G extends Game>

仍然没有成功。

我不知道Generic类型之间是否存在这种循环依赖关系,但似乎我已经陷入了嵌套泛型的鸡蛋情况。

有没有办法正确完成这项工作?不幸的是,我需要具体的GameTableGame类型来了解彼此,因为需要引用另一个。

3 个答案:

答案 0 :(得分:1)

你真的需要这种依赖性GameTable&lt; - &gt;游戏? GameTable是否足以通过使用指示表类型的枚举从gameFactory.getGameInstance()中检索游戏实例?基本上我会尝试减少接口/接口和类/接口之间的依赖关系。

答案 1 :(得分:1)

您使用非泛型的混合泛型,这往往会导致混淆。在Game中你给它了两个泛型参数类型,但在GameFactory中它被视为非泛型。尝试使所有类型始终保持通用或非通用,并且它应该有效。

e.g。

public interface GameFactory<T extends GameTable, P extends Player, G extends Game<T,P>> {
    public G getGameInstance(T table, List<P> players)
} 

或者更好地不指定返回的实现类。毕竟它是一个隐藏细节的工厂,就像它返回的具体类一样。

public interface GameFactory<T extends GameTable, P extends Player> {
    public Game<T,P> getGameInstance(T table, List<P> players)
} 

答案 2 :(得分:0)

问题是,你的GameFactory返回“G extends Game”,你试图将它分配给另一个可能不是同一类的“G extends Game”(即使它实际上在你的实现中)。

解决这个问题的一种方法是GameFactory返回“游戏”,而不是“扩展游戏的东西”。