我是来自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也是一个有效值?
答案 0 :(得分: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 :(得分:1)
首先,我想你想让value
,leftChild
,rightChild
和parent
受到保护,而非隐私,这样他们就可以可以从子类访问。
完成更改后,只需按以下方式定义子类,即可BIntTree.getLeftChild()
返回BTree<Integer>
:
public class BIntTree extends BTree<Integer> {
public BTree<Integer> getLeftChild() { return this.leftChild; }
...
}
我只想补充一点,如果你在这里发生了一些Integer
特定的逻辑,你应该真正定义这样一个类。否则,将T
的类型保留为使用BTree
类的任何人都是有意义的。
答案 2 :(得分:1)
您可以覆盖所需的方法,如下所示:
public class BIntTree extends BTree<Integer> {
@Override
public BIntTree getLeftChild() { return (BIntTree) super.getLeftChild(); }
}
从Vertion 1.5开始,Java支持协变返回类型 - 这意味着您可以使用它的子类返回类型。