I have a superclass which implements the Comparable
Interface and overrides the compareTo()
method. One subclass of this superclass has to implement it's own compareTo()
method but I'm not able to override the compareTo()
method of the superclass due to the name clash error.
public abstract class Superclass<T> implements Comparable<T> {
public int compareTo(T bo) { };
}
public class Subclass extends Superclass<Subclass> {
public <T> int compareTo(T bo) { }; // I get the name clash error here
}
To solve this problem I tried to make the subclass generic too (see: Java Generics name clash, method not correctly overridden), but either I did it wrong or this doesn't work:
public abstract class Superclass<T> implements Comparable<T> {
public int compareTo(T bo) { };
}
public class Subclass<T> extends Namable<Subclass<?>> {
public int compareTo(T bo) { }; // I get the name clash error here
}
So, how can I override the compareTo()
method of Superclass?
I think you have a more general design issue here. Namely, why do you want to implement compareTo
in the base class? In practice, this almost always leads to problems down the line.
Consider
public class Subclass2 extends Superclass<Subclass2> {
...
}
Subclass sub = new Subclass();
Subclass2 sub2 = new Subclass2(); // the superclass portions of the two objects
// are identical
sub2.compareTo(sub); // what should be the result?
If you have two Superclass
instances (whose superclass portions are identical, but the subclass portions may not be), how can you compare them using Superclass.compareTo
? If you don't take concrete subclasses into account, the result of the comparison is 0, incorrectly. If you try to directly compare objects of different subclasses, you will fail with a runtime exception. If you try to be clever and check the runtime types of the objects before trying to directly compare them, again you need to throw some sort of runtime exception instead of returning a valid-looking result.
I think it would be better to reverse the schema and implement compareTo
only in concrete subclasses where the compiler may ensure that the method is called with the right type of parameter. If you are worried about duplicating code between subclasses, you may pull it up into a protected final
method in the superclass.
Code example:
public abstract class Superclass {
protected final int compareBasePortionTo(Superclass other) { ... };
}
public class Subclass extends Superclass implements Comparable<Subclass> {
public int compareTo(Subclass other) {
int baseCmp = compareBasePortionTo(other);
if (baseCmp != 0)
return baseCmp;
// compare subclass properties
};
}
This compiles without warnings:
public abstract class Superclass<T> implements Comparable<T>{
@Override
public int compareTo(T o){
return 0;
};
}
public class Subclass extends Superclass<Subclass>{
@Override
public int compareTo(Subclass o){
return 0;
}
}
The problem with your version is that you were using a different T
. The T
you were using was the <T>
defined by the method, whereas the original T
from SuperClass<T>
was substitutes by SubClass
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With