Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java name clash error

Tags:

java

generics

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?

like image 416
syras Avatar asked Feb 24 '23 22:02

syras


2 Answers

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.

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
  };
}
like image 121
Péter Török Avatar answered Feb 27 '23 12:02

Péter Török


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.

like image 20
Sean Patrick Floyd Avatar answered Feb 27 '23 12:02

Sean Patrick Floyd