假设我有这两个继承层次结构:
class EntityA { ... }
class EntityB extends EntityA { ... }
class EntityAPrime extends AbstractPrime<EntityA> { ... }
class EntityBPrime extends EntityAPrime { ... }
我还想要协变返回类型:
public class EntityA {
public EntityAPrime prime() {
return new EntityAPrime();
}
}
public class EntityB extends EntityA {
@Override
public EntityBPrime prime() {
return new EntityBPrime();
}
}
到目前为止一切顺利。
问题是我想要EntityBPrime
最终延长AbstractPrime<EntityB>
但由于它扩展了 EntityAPrime
它最终延伸AbstractPrime<EntityA>
.
我可以做EntityAPrime
和EntityBPrime
通用,但随后我失去了协变返回类型:
public class EntityA {
public EntityAPrime<EntityA> prime() {
return new EntityAPrime();
}
}
public class EntityB extends EntityA {
@Override
public EntityBPrime<B> prime() { // ERROR: EntityBPrime extends EntityAPrime
return new EntityBPrime(); // but can't substitute <EntityB> for <EntityA>
}
}
如果我返回绑定(bind)通配符,一切正常,但有 disadvantages与此相关,我将无法在 AbstractPrime
上调用特定的 setter .
我的另一个想法是制作 EntityA
和EntityB
它们本身是通用的。
public class EntityA<T extends EntityA> {
public EntityAPrime<T> prime() { ... }
}
public class EntityB<T extends EntityB> extends EntityA<T> {
@Override
public EntityBPrime<T> prime() { ... }
}
这应该可行,但我认为它会变得困惑(我们有超过 100 个实体会使用类似的模式)。
那么,有什么办法:
- 保持协变返回
- 不在
EntityA
上使用泛型和EntityB
- 没有
prime()
返回绑定(bind)的通配符 - 并且有
EntityBPrime
最终延长AbstractPrime<EntityB>
而不是AbstractPrime<EntityA>
注意:主要类是生成的代码,但我可以控制生成的代码。
最佳答案
首先,你的接口(interface)和类都被称为A
,这有点令人困惑。和B
。因此,我将这些类重命名为 AImpl
和BImpl
分别。另外,你的类(class)APrime
和BPrime
没有输入(它们需要输入),所以我假设它们是在 <T extends A>
上输入的和<T extends B>
分别(如果我误解了您的意图/目标/要求,我深表歉意)。
private interface A {}
private interface B extends A {}
private abstract class AbstractPrime<T extends A>{}
private class APrime<T extends A> extends AbstractPrime<T>{}
private class BPrime<T extends B> extends APrime<T>{}
private class AImpl {...}
private class BImpl {...}
正如您所考虑的那样,我的第一直觉是在接口(interface)上键入实现。这会起作用:
private class AImpl<T extends A> {
public APrime<T> prime(){
return new APrime<>();
}
}
private class BImpl<T extends B> extends AImpl<T> {
public BPrime<T> prime(){
return new BPrime<>();
}
}
但是,如果您输入 APrime
上<T extends A>
和BPrime
上<T extends B>
,是否需要prime()
的返回类型要打字吗?以下解决方案可能适合您吗?
class APrime<T extends A> extends AbstractPrime<T>{}
class BPrime<T extends B> extends APrime<T>{}
public class AImpl {
public APrime prime(){
return new APrime<>();
}
}
public class BImpl extends AImpl {
public BPrime prime(){
return new BPrime<>();
}
}
我想这个问题的答案在某种程度上取决于您是否设想需要以下内容:
private interface C extends B {}
public void main(String[] args) {
BPrime<C> prime = new BImpl<C>().prime(); // do you need this?
BPrime<B> prime = new BImpl<>().prime(); // do you need this?
BPrime prime = new BImpl().prime(); or is this sufficient...?
}
关于具有泛型和协变返回的 Java 并行继承层次结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18472837/