My goal is very simple today, I am trying to work out the proper way to implement compareTo (or the Comparable) interface for my class which extends DefaultMutableTreeNode.
The problem is this: Say I have a perfectly good class that represents times. I've already written a perfectly good compareTo method (which works as I desire) that I've tested out with Arrays.sort() with marvelous results.
Now lets say I have a JTree with bunches of different objects, like this:
new SpecialNode("Zomg a string!"); // add this group of nodes right here
new SpecialNode(new Time("8:55 PM"));
new SpecialNode(new SomeTypeYouveNeverHeardOf());
So, being a professional programmer, I immediately start coding without any forethought whatsoever. Here is my SpecialNode class:
class SpecialNode extends DefaultMutableTreeNode implements Comparator<SpecialNode>
{
public int compareTo(SpecialNode sn)
{
// Not only does this not work correctly (read: at all)
// But, it is sub-par, how do I get the type information out of the userObject
// So I can cast it correctly and call the correct compareTo method!!
return this.getUserObject().toString().compareTo(sn.getUserObject().toString());
}
}
Ok, so if you didn't read the comments (which, admit, you didn't); My problem is that within the compareTo method of SpecialNode, I only have access to the userObject. Sadly, I do not know what the userObject used to be, and as such, I cannot properly cast it to call the correct compareTo method!
This is really a pain, since I've already written several perfectly good compareTo methods in all of the classes which will be added to my tree. So can someone help a guy out and drop me a hint?
tl;dr - How do I get type information out of an generic object that DefaultMutableTreeNode stores? If that is not possible, how should I go about comparing two instances of SpecialNode when I don't even know what they may contain!
Thanks in advance.
I'm assuming you can't have a TreeNode for each type of data. Does it make sense in your use case to do comparisons if the type is different?
Ideas:
Can SimpleNode know all of the possible types and do instanceof and casts to the correct type for Comparable? This is the way I would have handled it a few years ago.
How do you feel about unchecked warnings? I had a similar problem before using a JList and couldn't quite make the compiler happy (I gave up the swing default model to make my life easier). Maybe someone else could improve on this answer?
class SpecialNode<T extends Comparable<T>> extends DefaultMutableTreeNode
implements Comparable<SpecialNode>
{
T typedUserObject;
SpecialNode(T t)
{
this.typedUserObject = t;
setUserObject(t);
}
public int compareTo(SpecialNode node)
{
if(typedUserObject.getClass().isInstance(node.typedUserObject))
{
T otherObj = (T) node.typedUserObject;
return typedUserObject.compareTo(otherObj);
}
else
{
//What are you going to do if they're not the same type?
return -1;
}
}
}
Edit: If you know they should be the same type - eliminates check
class SpecialNode<T extends Comparable<T>> extends DefaultMutableTreeNode
implements Comparable<SpecialNode<T>>
{
T typedUserObject;
SpecialNode(T t)
{
this.typedUserObject = t;
setUserObject(t);
}
public int compareTo(SpecialNode<T> node)
{
return typedUserObject.compareTo(node.typedUserObject);
}
}
If you don't want the code in the node itself (I don't think I would), you might create a separate class that implements Comparator<SpecialNode<T>>