首页 文章

在超类方法中返回泛型超类的子类

提问于
浏览
3

我是来自PHP背景的Java新手,很抱歉,如果这很明显的话 . 我正在尝试实现二叉树类,我已经创建了一个ADT,如下所示:

public abstract class BTree<T> {
    private T value;
    private BTree<T> leftChild;
    private BTree<T> rightChild;
    private BTree<T> parent;
    public BTree<T> getLeftChild() { return this.leftChild; }
    ....
}

然后我有另一个类扩展这样的类:

public class BIntTree extends BTree<Integer> {
}

但是我希望能够在BIntTree中有一个方法,我可以调用 this.getLeftChild(); 并获取一个BIntTree实例而不是 BTree<Integer> 的实例

这可能通过某种方式定义泛型类/方法,或者在使用this.getLeftChild()后甚至覆盖超类方法时是否必须显式地输入它?

我目前的解决方案是使用 BIntTree b=(BIntTree) this.getLeftChild(); 在BIntTree方法中明确地对其进行类型转换,这对我来说似乎不整齐 .

此外,我不太确定如果我定义了类型转换并且getLeftChild()返回null会发生什么,是否会引发异常?如果是这样,我如何解决这个问题,因为如果存在,null也是一个有效值?

3 回答

  • 1

    您可以覆盖所需的方法,如下所示:

    public class BIntTree extends BTree<Integer> {
        @Override
        public BIntTree getLeftChild() { return (BIntTree) super.getLeftChild(); } 
    }
    

    从Vertion 1.5开始,Java支持协变返回类型 - 这意味着您可以使用它的子类返回类型 .

  • 4

    有可能有一个自我类型的类,但你不得不想知道为什么你想要它 . 为什么你需要知道它是 BIntTree 而不是 BTree<Integer> ?您使用仿制药获得了什么?

    无论如何,你可以做这样的事情:

    public abstract class BTree<V, T extends BTree<V, T>> {
        public T getLeft() {...}
        public T getRight() {...}
        public V getValue() {...}
    }
    

    然后你的 BIntTree

    public class BIntTree extends BTree<Integer, BIntTree> {
        //...
    }
    

    编辑

    关于你关于转换 null 的问题,实际上并没有什么能阻止你自己测试这个行为 . 但要回答你的问题,将 null 强制转换为任何类型都是安全的 .

  • 1

    首先,我想你想要保护 valueleftChildrightChildparent ,而不是私有,以便可以从子类访问它们 .

    完成更改后,只需定义子类,就可以 BIntTree.getLeftChild() 返回 BTree<Integer> ,如下所示:

    public class BIntTree extends BTree<Integer> {
        public BTree<Integer> getLeftChild() { return this.leftChild; }
        ...
    }
    

    我只想补充一点,如果你在这里发生了一些 Integer 特定的逻辑,你应该只定义这样一个类 . 否则,将 T 的类型留给使用 BTree 类的人是有意义的 .

相关问题