Why is it not possible to implement Comparable<T> multiple times?

2k Views Asked by At

It seems like you usually implemented the java.lang.Comparable interface without specifying the type parameter.

public abstract class Area implements Comparable {
    @Override
    public int compareTo(Object other) {
        if (other instanceof Area)
            return new Double(getArea()).compareTo(other.getArea());
        return -1; // or something else
    }
    abstract public double getArea();
}

Since I only want to compare apples with apples, I think it would make sense to specify the type.

public abstract class Area implements Comparable<Area> {
    @Override
    public int compareTo(Area other) {
        // ...

If I want to introduce another class to compare Area with, I thought I could do the following:

public abstract class Area implements Comparable<Area>, Comparable<Volume> {
    @Override
    public int compareTo(Area other) {
        // ...
    }
    @Override
    public int compareTo(Volume other) {
        // ...
    }
}

But the java compiler tells me:

Area.java:2: error: repeated interface
public abstract class Area implements Comparable<Area>, Comparable<Volume> {
                                                                   ^
Area.java:2: error: Comparable cannot be inherited with different arguments: <Area> and <Volume>
  1. Are there any drawbacks specifying the type argument for the generic interface?
  2. Why won't Java allow me this multiple implementation?

Note: I'm using Java version 1.7.0_45

2

There are 2 best solutions below

2
On BEST ANSWER
  1. No, it's not a drawback of specifying the generic - it's actually a feature. Also, I don't recall any drawback for using generics in interfaces, other than the well-known fact you can't instantiate a generic type nor create a generic array (but that's more a problem of implementation, not the interface itself).

  2. It's due to type erasure. Comparable<Area> and Comparable<Volume> is essentially the same class for the VM, and, shortly after checking validity, also for compiler.

If you want to have two distinct comparable interfaces implemented, just use Comparators for them - it's generally easier to maintain composition than inheritance in classes.

For some applications (distinguishing generics at run-time) you may also try subclassing them, e.g. ComparableArea extends Comparable<Area> & ComparableVolume extends Comparable<Volume>, but that would, in this particular case, cause more trouble than it would solve IMO, since you'd still get Comparable cannot be inherited with different arguments error - but at least you could differentiate those interfaces by e.g. instanceof.

0
On

I think this way java is saying that related classes can be Comparable, but using artificial Comparator we can do more comparisons among unrelated classes. So we should implement generic interface of related classes (classes within the same inheritance hierarchy). In case we want to add an artificial implementation, add an interface which can be passed through (so have pair of family of interfaces like Comparable and Comparator).