Reputation:
I am new to Java coming from a PHP background so sorry if this maybe obvious. I'm trying to implement a binary tree class and I've created an ADT like so:
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; }
....
}
Then I have another class that extends this like so:
public class BIntTree extends BTree<Integer> {
}
However I want to be able to within BIntTree to have a method where I can call this.getLeftChild();
and get an instance of BIntTree back rather than a instance of BTree<Integer>
Is this possible with some way of defining the generic class / method or do I have to explicitly type cast it after I used this.getLeftChild() or even override the superclass method?
My current solution is to explicitly typecast it in the BIntTree method with BIntTree b=(BIntTree) this.getLeftChild();
which seems untidy to me.
Also I'm not so sure what would happen if I had that type casting defined and getLeftChild() returned null, would an exception be thrown? If so how do I cure this given that null is also a valid value if exist?
Upvotes: 3
Views: 2145
Reputation: 81074
It is possible to have a self-typed class, but you have to wonder why you want it. Why do you need to know that it is a BIntTree
rather than a BTree<Integer>
? What have you gained with your use of generics?
Anyway, you could do something like this:
public abstract class BTree<V, T extends BTree<V, T>> {
public T getLeft() {...}
public T getRight() {...}
public V getValue() {...}
}
Then your BIntTree
would be
public class BIntTree extends BTree<Integer, BIntTree> {
//...
}
With regards to your question about casting null
, there is really nothing preventing you from testing the behaviour yourself. But to answer your question, it is safe to cast null
to any type.
Upvotes: 4
Reputation: 4697
You can override required method like this:
public class BIntTree extends BTree<Integer> {
@Override
public BIntTree getLeftChild() { return (BIntTree) super.getLeftChild(); }
}
As of vertion 1.5 Java supports covariant return types - meaning you can return type with it's subclass.
Upvotes: 1
Reputation: 21663
First of all, I would imagine that you'd want to make value
, leftChild
, rightChild
, and parent
protected, not private, so that they can be accessed from the subclass.
Once you make that change, you can have BIntTree.getLeftChild()
return a BTree<Integer>
simply by defining your subclass as follows:
public class BIntTree extends BTree<Integer> {
public BTree<Integer> getLeftChild() { return this.leftChild; }
...
}
I'll just add that you should only really be defining such a class if you have some Integer
-specific logic happening here. Otherwise, it would make sense to leave the type of T
up to whoever uses your BTree
class.
Upvotes: 1