Right now what your code says is:
There is a tree of type type
, which can be compared to other trees of type type
.
What you seemingly want to say is:
There is a tree, built from elements of type type
, which are comparable to their own type.
In that case, you should define tree like this:
public class Tree<T extends Comparable<T>> {
private class TreeNode<F extends<Comparable<F>> implements Comparable<TreeNode<F>>{
private F f;
...
public F getF(){return this.f;}
@Override
public int compareTo(TreeNode<F> node){
return this.f.compareTo(node.getF());
}
}
//Use TreeNode<T> here
...
}
Short summary: you have a Tree
of type T
, which is a type that can be compared to other objects of type T
. Elements in the tree are represented by TreeNode<T>
, which can be compared to other TreeNode<T>
. The comparison of a TreeNode<T>
to a TreeNode<T>
can be done by comparing the Elements stored inside the TreeNode
. There is a reason, why I have deviated from your original design in the last point (by name at least). If you think of T
as the stored item, it is easier to think about how to extend the tree to support an item of type TreeItem, which enables you to build an associative data-structure on top of the tree.
Edit (in direct response, since OP requested clarification):
OP's code was something like this at the time of answer:
public class Tree<T> implements Comparable<Tree<T>>{
...
TreeNode<???>{...}
}
Think of the TreeNode
having a fixed member int key;
for a second. You want to build a Tree
: So you need TreeNode
s, which can be compared to each other (i.e. TreeNode implements Comparable<TreeNode>
)to build a Tree
. You implement compareTo with int
-comparisons. You now have a non-generic Tree
.
To be able to make Tree
generic, you need a generic TreeNode
. So you make TreeNode
generic and replace the formerly fixed field int key;
by F f;
. Now you can no longer implement comparison based on int-comparisons, so TreeNode
has to be comparable to other instances of TreeNode
somehow. It would be cool, if we could delegate that to F
's comparison function. To make sure that works, the type has to be TreeNode<F extends Comparable<F>>
. Of course we still need the basic hypothesis of comparable TreeNode
s to hold so you end up with
class TreeNode<F extends<Comparable<F>> implements Comparable<TreeNode<F>>
.
You now have a generic TreeNode<F>
, that can be compared to other instances of TreeNode<F>
.
Now you can build a generic Tree<T>
from these nodes, as long as T is something that can be compared to other T
s, so Tree<T extends Comparable<T>>
. Since you don't want to shadow the type of the inner class you differentiate between T and F and instantiate TreeNode<T>
s when you use them inside the tree's functions. The existence of F
is not seen from the outside.