Java 不强制转换的继承
Java Inheritance without casting
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 的角度来处理它。但是我试图找出一种方法让继承的 class 将它的一些基础 class 变量视为它自己的类型(即 parent,left,right 在调用时应该被视为 BSTVertex
来自 BSTVertex
,但当从 BinaryVertex
) 调用时被视为 BinaryVertex
,无需转换。
我正在考虑泛型,但我不确定在这种情况下如何实现它。
更新
很好,不知道您可以在泛型中使用扩展。但是我收到 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 需要 return 一个与调用者类型相同的顶点,即如果 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
接口实现的方式相同,因此 subclasses 接收与 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()
方法中有一个编译错误:你的 class 以后可能会以一种使你的 T
与此不兼容的方式扩展。
您可以通过执行未经检查的转换来解决此问题:
@SuppressWarnings("unchecked")
public T foo() {
return (T) this;
}
这样如果你错误地创建class AVLVertex extends BSTVertex<RBVertex>{}
,它仍然会编译,但是在调用AVLVertex.foo()
时你可能有一个运行时ClassCastException
。
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 的角度来处理它。但是我试图找出一种方法让继承的 class 将它的一些基础 class 变量视为它自己的类型(即 parent,left,right 在调用时应该被视为 BSTVertex
来自 BSTVertex
,但当从 BinaryVertex
) 调用时被视为 BinaryVertex
,无需转换。
我正在考虑泛型,但我不确定在这种情况下如何实现它。
更新
很好,不知道您可以在泛型中使用扩展。但是我收到 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 需要 return 一个与调用者类型相同的顶点,即如果 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
接口实现的方式相同,因此 subclasses 接收与 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()
方法中有一个编译错误:你的 class 以后可能会以一种使你的 T
与此不兼容的方式扩展。
您可以通过执行未经检查的转换来解决此问题:
@SuppressWarnings("unchecked")
public T foo() {
return (T) this;
}
这样如果你错误地创建class AVLVertex extends BSTVertex<RBVertex>{}
,它仍然会编译,但是在调用AVLVertex.foo()
时你可能有一个运行时ClassCastException
。