public class BinaryVertex {
  public BinaryVertex parent,left,right;
}

public class BSTVertex extends BinaryVertex {
  public void foo() {
    left = new BSTVertex();
    if(Math.floor(Math.random()*2) == 0) left.foo();
  }
}


我正在为学校制作树/图api,从oop的角度出发。但是我试图找出一种方法来让继承的类将某些基类变量视为自己的类型(即,当从BSTVertex调用时,将parent,left,right视为BSTVertex,但应将其视为BinaryVertexBinaryVertex调用时),而无需强制转换。

我在考虑泛型,但不确定在这种情况下如何实现。

更新

很好,不知道您可以在泛型中使用扩展。但是我收到了一个BSTVertex<T> cannot be converted to T错误:

public class Test {
  public static void main(String[] args) {
  new AVLVertex();
  BSTVertex<BSTVertex> v = new BSTVertex<BSTVertex>();
  v.foo();
}
class BinaryVertex<T extends BinaryVertex> {
  public T parent, left, right;
}
class BSTVertex<T extends BSTVertex> extends BinaryVertex<T> {
  public T foo() {
    return this; //error here
  }
}
class AVLVertex extends BSTVertex<AVLVertex> {
  // this might probably end up being abstract too
}


foo需要返回与调用者相同类型的顶点,即如果AVLVertex调用foo,则其期望获取AVLVertex而不是BSTVertex

最佳答案

是的,您可以使用以下泛型:

public class BinaryVertex<T extends BinaryVertex<T>> {
    public T parent, left, right;
}

public class BSTVertex extends BinaryVertex<BSTVertex> {
  public void foo() {
    left = new BSTVertex();
    if(Math.floor(Math.random()*2) == 0) left.foo();
  }
}


Comparable接口的实现方式相同,因此子类接收与compareTo方法相同的类型。例如,Integer implements Comparable<Integer>,因此其compareTo方法将接收Integer参数。

另外请注意,最好像这样创建自己的随机数生成器:

public class BSTVertex extends BinaryVertex<BSTVertex> {
  private static final Random r = new Random();
  public void foo() {
    left = new BSTVertex();
    if(r.nextBoolean()) left.foo();
  }
}


更新

在您更新的代码中(以后请再问一个新问题),您不能安全地进行强制转换,因为您以后可能会写:

class RBVertex extends BSTVertex<RBVertex>{}
class AVLVertex extends BSTVertex<RBVertex>{}


从编译器的角度来看这是可以的,但是您的AVLVertex泛型参数实际上不是AVLVertex。这就是为什么您在foo()方法中出现编译错误的原因:您的类以后可能会以使您的T与之不兼容的方式扩展。

您可以通过执行未经检查的强制转换来解决此问题:

@SuppressWarnings("unchecked")
public T foo() {
    return (T) this;
}


这样,如果您错误地创建了class AVLVertex extends BSTVertex<RBVertex>{},它仍然可以编译,但是在调用AVLVertex.foo()时,您可能会有运行时ClassCastException

10-04 18:17