我正在为棋盘游戏平台创建一个小框架,我创建了以下界面,以便尽可能通用我将在此框架中放置的游戏。
我想使用Java Generics,这样每个实现都不仅如此 以适当的OO方式实现各自的接口,但也具有特定于游戏的要求的特定具体类可访问和强类型(没有强制转换等)。
例如,CheckersPlayer
会延伸Player
(CheckersPlayerImpl
实施CheckersPlayer
},CheckersGame
会延伸Game
(CheckersGameImpl
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类型之间是否存在这种循环依赖关系,但似乎我已经陷入了嵌套泛型的鸡蛋情况。
有没有办法正确完成这项工作?不幸的是,我需要具体的GameTable
和Game
类型来了解彼此,因为需要引用另一个。
答案 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返回“游戏”,而不是“扩展游戏的东西”。