Search code examples
javainterfacecomparecomparablemultiple-interface-implem

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


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


Solution

    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.