Java 重写参数类型引用自己的类的方法

Java 重写参数类型引用自己的类的方法,java,Java,我有以下java代码: public class TreeNode<T> { public TreeNode<T> getParent() { return null; } public void setParent(TreeNode<T> parent) { } public List<TreeNode<T>> getChildren() { return

我有以下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) {

    }
}
公共类树节点{
公共树节点getParent(){
返回null;
}
public void setParent(TreeNode parent){
}
公共列表getChildren(){
返回null;
}
公共子项(列出子项){
}
公共T getData(){
返回null;
}
公共无效设置数据(T数据){
}
}
现在,我想创建一个扩展上述类的类,如下所示:

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) {

    }

}
公共类二进制TreeNode扩展TreeNode{
公共二进制树节点getLeftChild(){
返回null;
}
公共void setLeftChild(){
}
公共二进制树节点getRightChild(){
返回null;
}
公共无效setRightChild(){
}
@凌驾
公共子项(列出子项){
}
}
但是,最后一个方法不会编译,因为参数
children
不是
List
类型。我理解为什么会发生这种情况(因为
List
不被视为
List
的子类型),但解决这种问题的最佳方法是什么


我知道我可以将
children
参数定义为
List
类型,但是如果可能的话,我想强制它为
List
类型。问题不在于列表不是子类,而是因为您无法重写方法并向上转换其参数

如果您有以下课程:

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);
当该代码运行时,它将尝试在没有该函数的实例上执行函数“problem”。 这就是为什么通常不能用继承原始类型的类重写参数

现在,您可以将参数保留为List>children,但是您可能会得到非二进制的节点,我假设您不需要


如果您确定这就是您希望继承的方式,您可以在方法开头检查“children”的类型,如果不合适,则抛出异常。

总结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) {}
}
公共类树节点{
public N getParent(){return null;}
public void setParent(N parent){}
公共列表getChildren(){return null;}
public void setChildren(列出子项){}
public T getData(){return null;}
公共void setData(T data){}
}
缺点是您的节点现在必须使用“冗余”泛型类型进行分类。这是因为您试图反驳这样一个事实,即子类可以充当超类的对象

您的二进制节点类如下所示:

class BinaryTreeNode<T> extends TreeNode<T, BinaryTreeNode<T>>
类BinaryTreeNode扩展了TreeNode

作为另一种选择和进一步阅读,请尝试以下文章:


尝试列表添加标识当前类型的通用参数,例如,
class TreeNode
。并使方法
setChildren(List children)
。如果BinaryTreeNode的唯一子元素是BinaryTreeNodes,那么叶子是什么类型?@andythonas BinaryTreeNodes,但没有自己的子元素。@shmosel我也有同样的想法,但您需要更改子元素的子元素类型。正如你所写的,孩子们有相同类型的孩子。实际上,它应该是
类TreeNode
,因为祖父可能不知道孙子的类型。您不需要公开子类中的第二个参数。请参阅我上面的评论。谢谢,单击花了一些时间。父类型可能也应该是
N
。不过,我认为仍然可以通过游戏将此结构与节点混合。是的,这是Java中泛型不可避免的现实。