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类型。我不想做任何禁止警告
答案 0 :(得分:1)
重要的是要理解每个类型参数化类的类型参数都是它自己的。特别是,它们(参数本身)不与超类或子类共享。类型参数化子类通常与其超类有意共享类型参数值,但这是另一回事。
类可以指定他们的超类,但他们不会改变他们的超类&#39;自己的继承。因此,如果SubClass1
扩展BaseClass<SubClass1<T>>
,那么BaseClass
类SubClass1<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;
}
}