Что должен вернуть CompareTo (), если аргументом является разная реализация одного и того же интерфейса? - PullRequest
0 голосов
/ 18 мая 2018

Имеет интерфейс

interface Animal extends Comparable<Animal> {
}

и 2 класса

class Dog implements Animal {

}

и

class Cat implements Animal {

}

Что compareTo(Animal o) должно возвращать, когда аргумент не является той же конкретной реализациейиз Animal?

Должно ли оно выбросить IllegalArgumentException?

Например, если я передам Dog экземпляр Cat.compareTo().Я не могу их сравнить, так как они разных типов.Я не могу сослаться на super.compareTo(), поскольку их супер имеет тип Object, который не реализует Comparable.Кастинг Dog на Cat будет выбрасывать ClassCastException.

Ответы [ 5 ]

0 голосов
/ 18 мая 2018

Это действительно зависит от того, хотите ли вы сравнить кошку и собаку.Вообще говоря, существуют различные возможности

  1. Сравнить все экземпляры животных с порядком в соответствии с Равным

    Вы можете, например, использовать разные атрибуты животныхтаким образом, что 2 разных животных не могут иметь все атрибуты одинаково.Если это имеет смысл, вы можете использовать имя класса в качестве такого атрибута, чтобы сравнить кошку и собаку, у которых все остальные атрибуты идентичны

  2. Сравнить все экземпляры животных с порядком несогласованныйс равным

    Просто небольшое отклонение от приведенного выше: два животного сравнятся равными , если их атрибуты идентичны, даже если equals между ними вернет false.Осторожно, это может быть опасно (даже если возможно), в соответствии с Javadoc для Comparable

    Настоятельно рекомендуется (хотя и не обязательно), чтобы естественные упорядочения были совместимы с равными.Это так, потому что отсортированные наборы (и отсортированные карты) без явных компараторов ведут себя «странно», когда они используются с элементами (или ключами), чье естественное упорядочение несовместимо с равенством.В частности, такой отсортированный набор (или отсортированная карта) нарушает общий контракт для набора (или карты), который определяется с помощью метода equals.

  3. Только сравнениеЭкземпляры животных в одном классе (и, конечно, его подклассы).В этом случае объявление интерфейса должно быть изменено для использования обобщений:

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

    и 2 класса

    class Dog implements Animal<Dog> {
    
    }
    

    и

    class Cat implements Animal<Cat> {
    
    }
    
0 голосов
/ 18 мая 2018

Интерфейс comparable говорит только о том, как работать вместе с 'equals', например, что compateTo() должен возвращать 0, если equals возвращает 0. https://docs.oracle.com/javase/8/docs/api/index.html?java/lang/Comparable.html

Так что на самом деле этозависит.Если это имеет смысл для вашей программы, вы можете привести к Animal:

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

Так что, если вы хотите отсортировать Animal по размеру или количеству результатов поиска в Google с помощью compareTo, это будетбыть действительной реализацией.

0 голосов
/ 18 мая 2018

interface Animal не должен реализовывать Comparable<Animal> во-первых, если вы не хотите, чтобы его подклассы были взаимно сопоставимыми.

Есть релевантная цитата из Effective Java 2nd Ed, в пункте 8 «Рассмотрите возможность реализации сопоставимого» (я скопировал большую часть следующего из моего ответа на этот вопрос ):

Одно из следствий этих трех положений [compareTo контракт] заключается в том, что тест на равенство, налагаемый методом сравнения, должен подчиняться тем же ограничениям, налагаемым контрактом на равенство: рефлексивность, симметрия и транзитивность.Следовательно, применяется то же самое предостережение: нет никакого способа расширить инстанцируемый класс новым компонентом значения при сохранении контракта CompareTo, если вы не хотите отказаться от преимуществ объектно-ориентированной абстракции (элемент 8).

Итак, это означает, что при условии, что ваш подкласс не имеет больше значений, чем суперкласс, используемый для определения порядка , реализация Comparable<Supertype> является разумной.

Смыслэто, в дополнение к общим требованиям Comparable, заключается в том, что Comparable<Superclass> должны быть реализованы одинаково в Superclass и во всех подклассах.

0 голосов
/ 18 мая 2018

Когда вы определяете Ainimal как:

interface Animal extends Comparable<Animal> {
}

, вы говорите, что любой Animal можно сравнить с другим Animal.

Если вы хотите только сравнитьDog до Dog, вы должны определить это так:

interface Animal {
}

class Dog implements Animal, Comparable<Dog> {

    @Override
    public int compareTo(Dog o) {
        ...
    }
}
0 голосов
/ 18 мая 2018

Он должен выдавать ошибку несоответствия и, если возможно, использовать оператор instanceOf для сопоставления связанных объектов перед сравнением.

...