Note that there are some explanatory texts on larger screens.

plurals
  1. POJava field type for a value of a generically recursive self-type?
    text
    copied!<p>Given a class hierarchy where the base class defines a recursive self-type:</p> <pre><code>abstract class A&lt;T extends A&lt;T&gt;&gt; { } </code></pre> <p>How can I declare another class (which should not be generic in T, because such a T could vary over the lifetime of the object) with a field that can hold any subclass of A?</p> <p>The following does not work:</p> <pre><code>public class B { //fails to compile, because the capture of ? is not sufficiently narrow private A&lt;?&gt; a; public &lt;T extends A&lt;T&gt;&gt; setA(T a) { this.a = a; } } </code></pre> <p>-- END OF QUESTION --</p> <p>I've noticed a tendency of a number of StackOverflow members to approach certain difficult questions with "why are you doing that in the first place?" The following is a justification of my use of this pattern - you can note that the Java standard library also uses recursive self-types in its definition of the Enum class: <code>Enum&lt;E extends Enum&lt;E&gt;&gt;</code>. This question could similarly be asked as "how to define a field of type <code>Enum&lt;?&gt;</code>.</p> <p>Justification example:</p> <pre><code>abstract class A&lt;T extends A&lt;T&gt;&gt; { public abtract T self(); public B&lt;T&gt; bify(Bifyer bifyer) { return bifyer.bify(self()); } } </code></pre> <p>with subclasses:</p> <pre><code>class ASub1 extends A&lt;ASub1&gt; { public ASub1 self() { return this; } } class ASub2 extends A&lt;ASub2&gt; { public ASub2 self() { return this; } } </code></pre> <p>bound to a parallel class hierarchy:</p> <pre><code>abstract class B&lt;T extends A&lt;T&gt;&gt; { } class BSub1&lt;T extends A&lt;T&gt;&gt; implements B&lt;T&gt; { } class BSub2&lt;T extends A&lt;T&gt;&gt; implements B&lt;T&gt; { } //and others </code></pre> <p>And with generation of B instances managed by implementations of a Bifyer interface:</p> <pre><code>interface Bifyer { B&lt;ASub1&gt; bify(ASub1 asub1); B&lt;ASub2&gt; bify(ASub2 asub2); } </code></pre> <p>Implementations of this interface may return a BSub1 or BSub2 for the B. This is essentially an application of the Visitor pattern where the Bifyer is the visitor, but unlike the standard Visitor the accept method returns a value instead of void. This provides a modular framework where different Bifyer implementations can be specified to provide alternate behavior and return types for the Bify method - say one for each subclass of B.</p>
 

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