Search code examples
javainterfacecomparable

What should compareTo() return if argument is different implementation of the same interface?


Having interface

interface Animal extends Comparable<Animal> {
}

and 2 classes

class Dog implements Animal {

}

and

class Cat implements Animal {

}

What compareTo(Animal o) should return when arguement is not the same concrete implementation of Animal?

Should it throw IllegalArgumentException?

As example if I pass Dog instance to Cat.compareTo(). I can not compare them as they are different types. I can not refer to super.compareTo() as their super is Object type which doesn't implement Comparable. Casting Dog to Cat will throw ClassCastException.


Solution

  • interface Animal shouldn't be implementing Comparable<Animal> in the first place if you don't want its subclasses to be mutually comparable.

    There is a relevant quote from Effective Java 2nd Ed, in Item 8 "Consider implementing Comparable" (I copied much of the following from my answer to this question):

    One consequence of these three provisions [of the compareTo contract] is that the equality test imposed by a compareTo method must obey the same restrictions imposed by the equals contract: reflexivity, symmetry, and transitivity. Therefore the same caveat applies: there is no way to extend an instantiable class with a new value component while preserving the compareTo contract, unless you are willing to forgo the benefits of object-oriented abstraction (Item 8).

    So, what this says is that provided your subclass doesn't have any more values than the superclass used to determine ordering, implementing Comparable<Supertype> is reasonable.

    The implication of this, in addition to the general requirements of the Comparable, is that Comparable<Superclass> should be implemented identically in Superclass and all subclasses.