我有以下java代码:
public class TreeNode<T> {
public TreeNode<T> getParent() {
return null;
}
public void setParent(TreeNode<T> parent) {
}
public List<TreeNode<T>> getChildren() {
return null;
}
public void setChildren(List<TreeNode<T>> children) {
}
public T getData() {
return null;
}
public void setData(T data) {
}
}
现在,我想创建一个扩展上面一个的类,如下所示:
public class BinaryTreeNode<T> extends TreeNode<T> {
public BinaryTreeNode<T> getLeftChild() {
return null;
}
public void setLeftChild() {
}
public BinaryTreeNode<T> getRightChild() {
return null;
}
public void setRightChild() {
}
@Override
public void setChildren(List<BinaryTreeNode<T>> children) {
}
}
但是,最后一种方法不会编译,因为参数children
不是List<TreeNode<T>>
类型。我理解为什么会发生这种情况(因为List<BinaryTreeNode<T>>
不被视为List<TreeNode<T>>
的子类型),但修复此类内容的最佳方法是什么?
我知道我可以将children
参数定义为List<TreeNode<T>>
类型,但如果可能,我希望将其强制为List<BinaryTreeNode<T>>
类型。
答案 0 :(得分:0)
这个问题不是来自不是子类的列表,而是因为你不能覆盖一个方法并将其参数翻转。
如果您有以下课程:
public class A
{
public void f(A a) {}
}
public class B extends A
{
public void problem(){}
public void f(B a)
{
a.problem();
}
}
由于B从A扩展,您可以运行以下代码:
A a1 = new B();
A a2 = new A();
a1.f(a2);
当该代码运行时,它将尝试在没有它的A实例上执行函数“problem”。 这就是为什么通常你不能用继承原始类型的类覆盖参数。
现在,您可以将参数保留为List&gt;孩子,但是你可能会得到非二进制的节点,我认为你不需要它。
如果您确定这是您希望继承的方式,则可以在方法开头检查“children”的类型,如果不适合则抛出异常。
答案 1 :(得分:0)
总结一下shmosel的建议:
public class TreeNode<T, N extends TreeNode<T, N>> {
public N getParent() { return null; }
public void setParent(N parent) {}
public List<N> getChildren() { return null; }
public void setChildren(List<N> children) {}
public T getData() { return null; }
public void setData(T data) {}
}
缺点是您的节点现在必须输入&#34;冗余&#34;通用类型。那是因为你试图反击子类可以作为超类对象的事实。
你的二进制节点类看起来像这样:
class BinaryTreeNode<T> extends TreeNode<T, BinaryTreeNode<T>>
作为替代方案并进一步阅读,请尝试以下文章: