从超类型方法返回子类类型

时间:2015-05-21 20:13:32

标签: java generics

public abstract class BaseClass<T extends BaseClass<T>> {

    T method1(){
        return getThis();
    }

    public  abstract T getThis();
}

public class SubClass extends BaseClass<SubClass> {
    public SubClass getThis(){
        return this;
    }
}

如果它只是一个继承级别,我可以执行类似上面的操作,并在调用method1()时获取SubClass的引用。

如果我有两个级别的继承,如

,该怎么办?
public abstract class SubClass1<T extends SubClass1<T>> extends BaseClass<SubClass1<T>> {
    @Override
    public SubClass1<T> getThis() {
        return this;
    }
}

public class SubSubClass1 extends SubClass1<SubSubClass1> {



}

我应该更改为method1和BaseClass,以便在调用method1时我可以返回SubSubClass1类型。我不想做任何禁止警告

2 个答案:

答案 0 :(得分:1)

重要的是要理解每个类型参数化类的类型参数都是它自己的。特别是,它们(参数本身)不与超类或子类共享。类型参数化子类通常与其超类有意共享类型参数,但这是另一回事。

类可以指定他们的超类,但他们不会改变他们的超类&#39;自己的继承。因此,如果SubClass1扩展BaseClass<SubClass1<T>>,那么BaseClassSubClass1<T> 的类型参数,其每个子类为{{1}因为那个类是SubClass1<T>扩展的那个类。

SubClass1<T>的任何具体子类都必须实现其抽象方法BaseClass<T>,并且需要这样的类(例如getThis())来指定SubClass1&#39; s类型参数BaseClass作为可实例化的类型(否则它不能提供返回值)。从层次结构开始,子类可以使用协变返回类型来缩小T返回的类型,但它们不能更改getThis()指定的BaseClass类型参数,除了范围这取决于SubClass1自己的类型参数。例如,这可以干净地编译:

SubClass1

但这是协变返回类型的练习,而不是类型参数化,所以这也有效:

public abstract class BaseClass<T extends BaseClass<T>> {
    // ...
    public  abstract T getThis();
}

public abstract class SubClass1<T extends SubClass1<T>> extends BaseClass<SubClass1<T>> {
    @Override
    public SubClass1<T> getThis() {
        return this;
    }
}

public class SubSubClass1 extends SubClass1<SubSubClass1> {
    @Override
    public SubSubClass1 getThis() {
        return this;
    }
}

推荐给@HannoBinder,他们首先在评论中提出了协变返回类型。

请注意,如果这里的主要想法是使用一个类型参数来标记你实际拥有的public abstract class BaseClass { // ... public abstract BaseClass getThis(); } public abstract class SubClass1 extends BaseClass { @Override public SubClass1 getThis() { return this; } } public class SubSubClass1 extends SubClass1 { @Override public SubSubClass1 getThis() { return this; } } 的后代 - 或者至少是它的上限 - 那么那就是错误的。在该方法中,类型BaseClass不比类型BaseClass<SomeSubClass>本身更有意义或更具表现力。参数化版本的区别仅在于难以使用。

答案 1 :(得分:1)

SubSubClass1必须是实施getThis()的人,如下所示:

public abstract class BaseClass<T> {
    T method1(){
        return getThis();
    }
    public abstract T getThis();
}

public abstract class SubClass1<T> extends BaseClass<T> {
}

public class SubSubClass1 extends SubClass1<SubSubClass1> {
    @Override
    public SubSubClass1 getThis() {
        return this;
    }
}
相关问题