第二次尝试this问题(初始代码不足以突出问题)
以下是无法编译的代码:
interface Player<R, G extends Game>
{
R takeTurn(G game);
}
interface Game<P extends Player>
{
void play(P player);
}
abstract class AbstractGame<R, P extends Player>
implements Game<P>
{
public final void play(final P player)
{
final R value;
value = player.takeTurn(this);
turnTaken(value);
}
protected abstract void turnTaken(R value);
}
public class XPlayer
implements Player<Integer, XGame>
{
@Override
public Integer takeTurn(final XGame game)
{
return (42);
}
}
public class XGame<P extends Player<Integer, XGame>>
extends AbstractGame<Integer, XPlayer>
{
@Override
protected void turnTaken(final Integer value)
{
System.out.println("value = " + value);
}
}
public class Main
{
public static void main(final String[] argv)
{
final XPlayer player;
final XGame game;
player = new XPlayer();
game = new XGame();
game.play(player);
}
}
我遇到的是试图让AbstractGame中的play方法进行编译。似乎我必须在游戏和玩家的圈子中运行,在扩展/实现中添加泛型,但对于我的生活,我无法直截了当。
play方法必须在AbstractGame类中是最终的,并且没有办法进行转换,我不想写另一个方法,如turnTaken,如果我不需要
编辑:这里要求的是编译的代码,但需要演员:
interface Player<R, P extends Player<R, P, G>, G extends Game<R, G, P>>
{
R takeTurn(G game);
}
interface Game<R, G extends Game<R, G, P>, P extends Player<R, P, G>>
{
void play(P player);
}
abstract class AbstractGame<R, G extends Game<R, G, P>, P extends Player<R, P, G>>
implements Game<R, G, P>
{
public final void play(final P player)
{
final R value;
value = player.takeTurn((G)this);
turnTaken(value);
}
protected abstract void turnTaken(R value);
}
class XPlayer
implements Player<Integer, XPlayer, XGame>
{
@Override
public Integer takeTurn(final XGame game)
{
return (42);
}
}
class XGame
extends AbstractGame<Integer, XGame, XPlayer>
{
@Override
protected void turnTaken(final Integer value)
{
System.out.println("value = " + value);
}
}
class Main
{
public static void main(final String[] argv)
{
final XPlayer player;
final XGame game;
player = new XPlayer();
game = new XGame();
game.play(player);
}
}
答案 0 :(得分:8)
混合泛型和原始类型不起作用。如果您需要这些接口相互引用,它们还需要引用自己:
interface Player<R, P extends Player<R, P, G>, G extends Game<R, G, P>>
{
R takeTurn(G game);
}
interface Game<R, G extends Game<R, G, P>, P extends Player<R, P, G>>
{
void play(P player);
}
虽然这看起来很像头发,但我不确定你为什么需要它。
修改强>
我能够根据以上内容实施您的AbstractGame
:
abstract class AbstractGame<R, P extends Player<R, P, AbstractGame<R, P>>>
implements Game<R, AbstractGame<R, P>, P>
{
public final void play(final P player)
{
final R value;
value = player.takeTurn(this);
turnTaken(value);
}
protected abstract void turnTaken(R value);
}
但是,我无法通过XGame
和XPlayer
:
public class XGame
extends AbstractGame<Integer, XPlayer> //compile error on XPlayer
{
protected void turnTaken(Integer value) { }
}
public class XPlayer
implements Player<Integer, XPlayer, XGame> //compile error on XGame
{
@Override
public Integer takeTurn(final XGame game)
{
return (42);
}
}
问题似乎是XGame
和XPlayer
的每个通用声明都需要另一个是正确的。这是您的设计真正具有周期性的地方。如果编译器“假定”每个都是正确的,那么它在理论上是可行的。但事实并非如此。
编辑2:
这个怎么样:
interface Game<R, G extends Game<R, G>>
{
void play(Player<R, G> player);
}
interface Player<R, G extends Game<R, G>>
{
R takeTurn(G game);
}
abstract class AbstractGame<R, G extends AbstractGame<R, G>>
implements Game<R, G>
{
public final void play(final Player<R, G> player)
{
final R value;
value = player.takeTurn(self());
turnTaken(value);
}
protected abstract G self();
protected abstract void turnTaken(R value);
}
public final class XGame extends AbstractGame<Integer, XGame>
{
protected XGame self() {
return this;
}
protected void turnTaken(Integer value) { }
}
public class XPlayer implements Player<Integer, XGame>
{
@Override
public Integer takeTurn(final XGame game)
{
return (42);
}
}
这里的关键是在self()
中声明一个抽象方法AbstractGame
,它返回一个类型为G
的实例。扩展类必须使用自己的类型解析继承的类型参数,并实现self()
以返回this
。这仅适用于内部代码,因为扩展类很容易存在,例如:
public class EvilGame extends AbstractGame<Integer, AnotherGame> { ... }
答案 1 :(得分:2)
正如Paul Bellora指出的那样,你正在混合通用和原始类型 - 正确的,完全通用的解决方案有点混乱,需要大量的冗余。在Java中做循环(但不是递归)泛型没有很好的方法(我知道)。
我不会挣扎于此,而是只使用Player
和Game
两个参数,即所使用的值的类型 - 你所拥有的R
。< / p>
interface Game<R> {
void play(Player<? extends R> player);
}
interface Player<R> {
R takeTurn(Game<? super R> game);
}
abstract class AbstractGame<R> implements Game<R> {
public final void play(Player<? extends R> player) {
final R value;
value = player.takeTurn(this);
turnTaken(value);
}
protected abstract void turnTaken(R value);
}
class XPlayer implements Player<Integer> {
@Override
public Integer takeTurn(Game<? super Integer> game) {
return 42;
}
}
class XGame extends AbstractGame<Integer> {
@Override
public void turnTaken(Integer value) {
System.out.println("value = " + value);
}
}
public class Main {
public static void main(String[] argv) {
XPlayer player = new XPlayer();
XGame game = new XGame();
game.play(player);
}
}
现在,任何知道如何采取基于R
的动作的玩家都可以玩任何基于R
的游戏。