Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Mixing generics and raw types isn't going to work. If you need these interfaces to reference each other, they also need to reference themselves:</p> <pre><code>interface Player&lt;R, P extends Player&lt;R, P, G&gt;, G extends Game&lt;R, G, P&gt;&gt; { R takeTurn(G game); } interface Game&lt;R, G extends Game&lt;R, G, P&gt;, P extends Player&lt;R, P, G&gt;&gt; { void play(P player); } </code></pre> <p>Although this is looking rather hairbrained, and I'm not sure why you need it.</p> <p><strong>Edit:</strong></p> <p>I was able to implement your <code>AbstractGame</code> based on the above:</p> <pre><code>abstract class AbstractGame&lt;R, P extends Player&lt;R, P, AbstractGame&lt;R, P&gt;&gt;&gt; implements Game&lt;R, AbstractGame&lt;R, P&gt;, P&gt; { public final void play(final P player) { final R value; value = player.takeTurn(this); turnTaken(value); } protected abstract void turnTaken(R value); } </code></pre> <p>However I couldn't quite close the circuit with <code>XGame</code> and <code>XPlayer</code>:</p> <pre><code>public class XGame extends AbstractGame&lt;Integer, XPlayer&gt; //compile error on XPlayer { protected void turnTaken(Integer value) { } } public class XPlayer implements Player&lt;Integer, XPlayer, XGame&gt; //compile error on XGame { @Override public Integer takeTurn(final XGame game) { return (42); } } </code></pre> <p>The issue seems to be that each of the generic declarations of <code>XGame</code> and <code>XPlayer</code> needs the other to be correct. This is where your design is truly cyclical. If the compiler 'assumed' each was correct, it would in theory work. But it doesn't.</p> <p><strong>Edit 2:</strong></p> <p>How about this:</p> <pre><code>interface Game&lt;R, G extends Game&lt;R, G&gt;&gt; { void play(Player&lt;R, G&gt; player); } interface Player&lt;R, G extends Game&lt;R, G&gt;&gt; { R takeTurn(G game); } abstract class AbstractGame&lt;R, G extends AbstractGame&lt;R, G&gt;&gt; implements Game&lt;R, G&gt; { public final void play(final Player&lt;R, G&gt; 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&lt;Integer, XGame&gt; { protected XGame self() { return this; } protected void turnTaken(Integer value) { } } public class XPlayer implements Player&lt;Integer, XGame&gt; { @Override public Integer takeTurn(final XGame game) { return (42); } } </code></pre> <p>The key here was declaring an abstract method <code>self()</code> in <code>AbstractGame</code> that returns an instance of type <code>G</code>. Extending classes must resolve the inherited type parameter with their own type, and implement <code>self()</code> to return <code>this</code>. This is only suitable for internal code, since an extending class could easily lie, for example:</p> <pre><code>public class EvilGame extends AbstractGame&lt;Integer, AnotherGame&gt; { ... } </code></pre> <p>See my answer <a href="https://stackoverflow.com/a/7355094/697449">here</a> and <a href="https://stackoverflow.com/questions/7959335/self-bound-generic-type-with-fluent-interface-and-inheritance">this post</a> for more details on this pattern.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload