Java name mapping error

I have a superclass that implements the Comparable interface and overrides the compareTo() method. One subclass of this superclass should implement its own compareTo() method, but I cannot override the compareTo() method of the superclass due to a 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 also tried to create a subclass of a general type (see Java Generics name collision, a method that was not correctly overridden ), but either I did it wrong or it does not 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 for a superclass?

+4
source share
2 answers

I think you have a more general design problem 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 instances of Superclass (whose parts of the superclass are identical, but the parts of the subclass cannot be), how can you compare them using Superclass.compareTo ? If you do not account for specific subclasses, the result of the comparison is 0, incorrect. If you try to directly compare objects of different subclasses, you lose with an exception from the runtime. If you try to be smart and check the runtime types of objects before trying to directly compare them, again you need to throw some sort of exception at runtime, rather than returning the correct result.

I think it would be better to cancel the scheme and implement compareTo only in specific subclasses where the compiler can guarantee that the method is called with the correct parameter type. If you are worried about code duplication between subclasses, you can translate it into the protected final method in the superclass.

Update

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 }; } 
+4
source

This compiles without warning:

 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 used a different T The T used was <T> defined by the method, while the original T from SuperClass<T> was replaced by SubClass .

+4
source

Source: https://habr.com/ru/post/1342279/


All Articles