我担心有关二叉搜索树的Java项目。我们被要求实现和AVL树,但也建议保持良好的抽象,以实现其他类型的树(如红黑树)。我决定使用abstract BsNode
类(Bs =二分搜索)和abstract BsTree
类,并通过以下方式使用AvlTree
和AvlNode
实现它们:
public abstract class BsNode<T extends BsNode> {
T parent
T left
T right
...
}
public abstract class BsTree<T extends BsNode> {
T root
...
}
public class AvlNode extends BsNode<AvlNode> {
int balance;
...
}
public class AvlTree<AvlNode> {
private void rotate(int direction);
...
}
这会导致两个问题:首先,BsNode
需要接收它的继承者类型并不意味着我。其次,这开启了发生这种事情的可能性:
public class RedBlackNode extends BsNode<AvlNode> {
...
}
或
RedBlackNode myRoot = new RedBlackNode<AvlNode>();
这些不应该被允许。如何在BsNode
中强制使用继承类(意味着保持parent
和子指针指向实现类的类型)而不是传递T
泛型变量?
答案 0 :(得分:1)
正如评论中所提到的,这不可能在编译时强制执行。有一种技巧可以在运行时强制它失败。
您要做的是请求实现类将自己的类型参数类传递给抽象构造函数,并使用类型参数类键入参数。
父类构造函数验证这个类确实是与类型参数对应的类相同的类。
abstract class BsNode<T extends BsNode<T>> {
protected BsNode(final Class<T> clazz) {
if (!this.getClass().equals(clazz))
throw new IllegalArgumentException("invalid mixture of node types");
}
}
class AvlNode extends BsNode<AvlNode> {
public AvlNode() {
super(AvlNode.class); // works!!!
}
}
class RBNode extends BsNode<AvlNode> {
public RBNode() {
// two possible super calls:
super(AvlNode.class); // fails at run-time.
// or
super(RBNode.class); // fail at compilation-time.
}
}
如果您的软件包含测试的正式构建过程,那么将约束检查留出生产代码(节省计算时间)可能更有意义,而是将其作为单元测试的一部分