假设我有两个继承层次结构:
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>
}
}
如果我返回绑定的通配符但是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()
返回绑定的通配符EntityBPrime
最终延长AbstractPrime<EntityB>
而不是AbstractPrime<EntityA>
注意:素数类是生成代码,但我可以控制生成代码。
答案 0 :(得分:1)
首先,您的接口和类都被称为A
和B
,这有点令人困惑。所以,我已经将这些类重命名为AImpl
和BImpl
。此外,您的课程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 {...}
正如您所考虑的,我的第一直觉是在接口上键入实现。这可行:
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...?
}
我想这个问题的答案在某种程度上是否需要以下内容:
{{1}}
答案 1 :(得分:1)
正如我在评论中所提到的,有很多地方类型params被省略,这使整个故事看起来不正确。
首先,你的Primes至少应该是这样的:
class EntityAPrime<T extends EntityA> extends AbstractPrime<T> {}
class EntityBPrime<T extends EntityB> extends EntityAPrime<T> {}
然后问题来到你的实体
class EntityA {
public EntityAPrime<????> prime(); <- What should be the reasonable type param here?
}
class EntityB extends EntityA {
public EntityBPrime<????> prime(); <- Same here
}
答案取决于您的设计。
我不知道你的第二选择是如何比原来的更糟糕(鉴于原来的那个是真正的凌乱)
你可以考虑这个(没有经过测试,根据你的设计,它是否正确,但至少类型参数对我来说是合理的):
public class Entity<T> {
public Prime<T> prime();
}
public class AbstractEntityA<T extends EntityA> extends Entity<T> {
@Override
public AbstractAPrime<T> prime();
}
public class EntityA extends AbstractEntityA<EntityA>{
public EntityAPrime prime() { ... }
}
public class EntityB extends AbstractEntityA<EntityB> {
public EntityBPrime prime() {...}
}
public class AbstractAPrime<T extends EntityA> extends AbstractPrime<T> {}
public class EntityAPrime extends AbstractAPrime<EntityA>{}
public class EntityBPrime extends AbstractAPrime<EntityB>{}
简而言之,将原始EntityA中的内容移动到一个抽象类,由EntityA扩展(主要是普通扩展)和EntityB(覆盖并添加更多内容)。同样适用于Prime。