Java field type for a value of a generically recursive self-type?

纵然是瞬间 提交于 2020-01-11 05:58:07

问题


Given a class hierarchy where the base class defines a recursive self-type:

abstract class A<T extends A<T>> { }

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?

The following does not work:

public class B {
    //fails to compile, because the capture of ? is not sufficiently narrow
    private A<?> a;

    public <T extends A<T>> setA(T a) {
        this.a = a;
    }
}

-- END OF QUESTION --

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: Enum<E extends Enum<E>>. This question could similarly be asked as "how to define a field of type Enum<?>.

Justification example:

abstract class A<T extends A<T>> {
    public abtract T self();
    public B<T> bify(Bifyer bifyer) {
        return bifyer.bify(self());
    }
}

with subclasses:

class ASub1 extends A<ASub1> { 
    public ASub1 self() { return this; }
}       

class ASub2 extends A<ASub2> { 
    public ASub2 self() { return this; }
}       

bound to a parallel class hierarchy:

abstract class B<T extends A<T>> {
}

class BSub1<T extends A<T>> implements B<T> { }
class BSub2<T extends A<T>> implements B<T> { }
//and others

And with generation of B instances managed by implementations of a Bifyer interface:

interface Bifyer {
    B<ASub1> bify(ASub1 asub1);
    B<ASub2> bify(ASub2 asub2);        
}

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.


回答1:


If you bound the wildcard ? below by A, it should work:

public class B {
    private A<? extends A> a;

    public <T extends A<T>> void setA(T a) {
        this.a = a;
    }
}


来源:https://stackoverflow.com/questions/695298/java-field-type-for-a-value-of-a-generically-recursive-self-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!