如果参数是同一接口的不同实现,compareTo() return 应该怎么办?

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

有接口

interface Animal extends Comparable<Animal> {
}

和 2 类

class Dog implements Animal {

}

class Cat implements Animal {

}

当争论与 Animal 的具体实现不同时,compareTo(Animal o) 应该 return 什么?

它应该抛出 IllegalArgumentException 吗?

例如,如果我将 Dog 实例传递给 Cat.compareTo()。我无法比较它们,因为它们是不同的类型。我不能引用 super.compareTo(),因为他们的 super 是 Object 类型,没有实现 Comparable。将 Dog 转换为 Cat 将抛出 ClassCastException.

它应该抛出不匹配错误,如果可能,在比较之前使用 instanceOf 运算符匹配相关对象。

如果您不希望其子类相互比较,

interface Animal 不应该首先实现 Comparable<Animal>

在第 8 项 "Consider implementing Comparable" 中有来自 Effective Java 第二版 的相关引用(我从 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).

所以,这就是说 假设您的子类没有比用于确定排序的超类更多的值,实施 Comparable<Supertype> 是合理的。

除了 Comparable 的一般要求外,这意味着 Comparable<Superclass> 应该在 Superclass 和所有子类中以相同的方式实现。

当您将 Ainimal 定义为:

interface Animal extends Comparable<Animal> {
}

你是说任何 Animal 都可以与另一个 Animal 进行比较。

如果你只想比较DogDog,你应该这样定义它:

interface Animal {
}

class Dog implements Animal, Comparable<Dog> {

    @Override
    public int compareTo(Dog o) {
        ...
    }
}

comparable 界面只说明了一些如何与 'equals' 一起工作的事情,例如,compateTo() 应该 return 0 如果 equalsreturns 0。 https://docs.oracle.com/javase/8/docs/api/index.html?java/lang/Comparable.html

所以实际上这取决于。 如果它对您的程序有意义,您可以转换为 Animal:

int compareTo(Dog o)
{
    Animal other = (Animal) o;
    ...
}

因此,如果您想使用 compareTo 根据大小或 Google 上搜索结果的数量对 Animal 进行排序,这将是一个有效的实现。

这实际上取决于您是否希望能够比较猫和狗。大体来说,有不同的可能性

  1. 比较所有Animal实例的顺序与Equal

    一致

    例如,您可以使用动物的不同属性,使 2 种不同的动物不能具有相同的所有属性。如果有意义,您可以使用 class 名称作为这样的属性来比较具有相同所有其他属性的猫和狗

  2. 比较所有 Animal 实例的顺序与 Equal

    不一致

    只是上面的一个细微变化:如果两个动物的属性相同,它们将 比较相等 ,即使它们之间的 equals 将 return 为假.当心,根据 Comparable

    的 Javadoc,这可能很危险(即使可能)

    It is strongly recommended (though not required) that natural orderings be consistent with equals. This is so because sorted sets (and sorted maps) without explicit comparators behave "strangely" when they are used with elements (or keys) whose natural ordering is inconsistent with equals. In particular, such a sorted set (or sorted map) violates the general contract for set (or map), which is defined in terms of the equals method.

  3. 只比较一个 class 中的 Animal 实例(当然还有它的子class)。在那种情况下,接口的声明应该改为使用泛型:

    interface Animal<T> extends Comparable<T> {
    }
    

    和 2 classes

    class Dog implements Animal<Dog> {
    
    }
    

    class Cat implements Animal<Cat> {
    
    }