2

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

Niklas R
  • 16,299
  • 28
  • 108
  • 203
  • I think the better question is, why do you think this would be beneficial? And how would `newYork.compareTo(eleven)` be apples to apples? :-) – Harald K Nov 20 '14 at 14:37

2 Answers2

5
  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.

  • 2
    I agree. If the OP wants to be able to compare multiple items that are not of the same type and don't share a common superclass, it's better to just write a `Comparator` that knows how to do that. Your `Area` classes shouldn't really (IMO) need to know that `Volume` classes exist, nor how to compare themselves. If *they did*, then wouldn't your `Volume` class also need to implement both `Comparable`s? You can see how this would quickly balloon out of control, as you add more types. – Craig Otis Nov 20 '14 at 14:31
  • @CraigOtis I wholeheartedly agree; I'll add that as a note to my answer. –  Nov 20 '14 at 14:32
-1

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).

ARC
  • 9
  • 3