I am creating subclass and have some class elements inside it. Now I want to override compareTo method from super class and use variables from subclass as argument in new compareTo method but I get error saying that the argument for compareTo method must be the same as in the superclass.
Is there any solution to this problem?
Thanks in advance!
Solutions that I tried are:
1)just simply to write new method in subclass (not to override method from super class) 2) create new compareTo method in superclass with arguments I want
this way program is working but I feel like that is not the correct way to fix this problem
Anyone can suggest something or give advice about this?
Okay.
Impossible.
Comparable is a 'contract interface' - you can't just implement the methods; you aren't "done" when you have implemented every method and they compile and (appear to) run without throwing exceptions: The documentation states additional rules you need to adhere to that the compiler cannot check. The fact that the compiler cannot check that you adhere to these rules means your code compiles. However, your code is still broken. ("It compiles" does not mean "It is correct", after all).
One of the rules in the contract is that comparison operations are commutative and associative: if
a.compareTo(b)returns a negative number, thenb.compareTo(a)must return a positive number, (and if one returns0so must the other) and vice versa. If you fail to adhere to the contract, crazy stuff happens. For example, you create aTreeSetand things end up out of order and this kind of code can start printingfalse:However, adhering to the contract (the commutativity) rule is not possible when you subclass and want to override definitions. Let's make it practical:
The above code doesn't work for two reasons: [A] it can't be made to compile, and [B] even if you voodoo magic that away with generics casting, the code breaks the contract. And always will, you can't fix [B].
So instead of delving deep on generics and working around it (which you can), it is a moot point - B cannot be worked around, so what you want is impossible, therefore there is no point explaining how to hack around so that the compiler accepts it.
The reason it's not possible is the commutativity rule. Let's consider 3 instances:
Your intent is very clearly that this happens:
However, what happens when p is involved? Remember,
Childsays that it is a subtype ofParentwhich means an instance of Child can do everything an instance of Parent can do, and more. One thing Parent can do, is compare itself to another instance of Parent. And instances of Child are also instances of Parent, so, you can compare a Parent to a Child and vice versa. Hence,p.compareTo(a)is valid. Similarly, you can make anew TreeSet<Parent>()and you can of course invoke.add(new Child())on that. After all, instances of Child are definitely also instances of Parent, that's what subclassing means.Thus:
Hence, what you want? Impossible. The contract of comparable forbids it.
Effectively, with Comparable, you 'pick a level' and comparability is defined strictly on that level, and subclasses cannot change that. Whatever type in your type hierarchy decides to
implements Comparable, that's the level. They set the baseline of the natural comparison for those things and subclasses cannot modify how that works at all without breaking the contract.What you probably want is to forget about natural order and use comparators instead. Every system that works on natural order (such as
TreeSet, orlist.sort(Comparator.naturalOrder())orCollections.sort(list)orArrays.binarySearch, and so on), also has an overloaded variant that accepts aComparator<T>.You CAN make a custom comparator that compares, specifically, children. You can even make a custom comparator that compares children and parents if you define the comparison operation properly (meaning, there is a complete order). For example, by saying that given equal
xvalues, anynew Parent()instance will always sort before anynew Child(), regardless of Child's y value: