Second attempt at this question (the initial code wasn\'t enough to highlight the issue)
Here is the code that does not compile:
interface Player<
As Paul Bellora points out, you're mixing generic and raw types -- and the correct, fully-generic solution is a bit of a mess and requires a lot of redundancy. There's no nice way (that I know of) to do circular (but not recursive) generics in Java.
Rather than struggling with this, I would make both Player
and Game
generic on just one parameter, the type of value being played with -- what you had as R
.
interface Game {
void play(Player extends R> player);
}
interface Player {
R takeTurn(Game super R> game);
}
abstract class AbstractGame implements Game {
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 {
@Override
public Integer takeTurn(Game super Integer> game) {
return 42;
}
}
class XGame extends AbstractGame {
@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);
}
}
Now, any player who knows how to take R
-based moves can play any R
-based game.