在尝试以逻辑方式构建我的类时,我发现了 Java 执行递归泛型的能力。这几乎正是我在结构方面寻找的东西,但我遇到了抽象类的问题。我认为 Foo 和 Bar 对于这个例子来说会非常困惑,所以我命名了与我的实际项目相关的类。
public abstract class GeneCarrier<T extends GeneCarrier<T>> {
protected Gene<T> gene;
//...
}
public class Gene<T extends GeneCarrier<T>> {
//...
}
public abstract class Organism extends GeneCarrier<Organism>{
//...
}
public class Human extends Organism {
public void foo(){
Gene<Human> g; // Bound mismatch: The type Human is not a valid substitute for the bounded parameter <T extends GeneCarrier<T>> of the type Gene<T>
}
}
我认为问题可能出在我的抽象 Organism
类的定义上,但这也产生了类似的错误:
public abstract class Organism extends GeneCarrier<? extends Organism>{
//...
}
尝试使用具有递归模板定义的抽象类是否存在固有问题,或者我在类定义中犯了错误?
最佳答案
Is there an inherent problem in trying to use an abstract class with recursive template definitions, or have I made a mistake in the class definitions?
看来你犯了一个错误。 Gene
上的递归界限的类型参数 T
需要 Human
的类型参数应该意味着 Human
是 GeneCarrier<Human>
.但它不是 - Human
是 GeneCarrier<Organism>
.
为了正确地实现这个模式,递归类型参数应该沿着继承树向下传播,直到它到达我喜欢称之为“叶”类的地方,在这种情况下似乎是Human
。 :
public abstract class Organism<T extends Organism<T>> extends GeneCarrier<T> {
//...
}
public final class Human extends Organism<Human> {
public void foo(){
Gene<Human> g; // valid
}
}
这解决了手头的问题,但您应该了解在 Java 中使用“ self 类型”(通常称为 Curiously Recurring Template Pattern)的优点和缺点。我在这篇文章中详细介绍了实现此模式及其陷阱:Is there a way to refer to the current type with a type variable?
总的来说,我发现开发人员尝试使用“ self 类型”,以便在某些类上实现类型安全的“复制”方法(这似乎是这种情况,因为您的类型名称与基因相关)。当发生这种情况时,我总是建议尝试将复制责任分离到一个单独的类型,以避免增加递归泛型的复杂性。 My answer here是一个例子。
关于java - 抽象递归泛型导致绑定(bind)不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22431364/