Интерфейсы в рамках коллекций

Мой вопрос

Интерфейс имеет метод add(E e) и расширяет интерфейс Collection. Интерфейс Collection также имеет метод add(E e) Итак, зачем нам нужен тот же метод в интерфейсе Set, поскольку он уже расширяет интерфейс Collection. В чем цель? Я застрял с этим

Ответы

Ответ 1

Поскольку два правильных ответа не смогли вас убедить, я попытаюсь объяснить.

Интерфейсы определяют контракты - то есть они определяют, какие реализаторы идут (и связаны), чтобы вы знали, что всякий раз, когда вы ссылаетесь на объект по интерфейсу, он имеет строго определенное поведение, независимо от того, как именно оно было реализованы.

Теперь этот контракт состоит из двух частей:

  • подпись метода - сигнатура метода - это элемент, который применяется компилятором - все разработчики должны соответствовать всем сигнатурам метода, определенным интерфейсом
  • документированное поведение - когда метод больше, чем его сигнатура метода, специальное поведение документируется. Он снова сообщает клиенту интерфейса, что ожидать от всех разработчиков, хотя он не технически принуждает разработчиков соответствовать ему.

И вот конкретный пример Collection/Set:

  • Если вы ссылаетесь на объект как на Collection, тогда вы ничего не знаете о поведении add - разрешаете ли вы дубликаты или нет
  • если вы ссылаетесь на объект как Set, то вы уверены, что дубликатов не разрешено.

Это различие выполняется с помощью javadoc переопределенного метода add.

Ответ 2

Set.add уточняет контракт Collection.add. Из последнего Джавадока:

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

То, что сделано в Javadoc Set.add, где указано, что, например, дублирующие элементы не добавляются в набор.

Обновление: по контрактам и интерфейсам

(включая и распространяя мои комментарии ниже, чтобы завершить этот ответ.)

Контракт метода указывает - формально или неформально - то, что ожидается, что вызывающий абонент предоставит в качестве ввода для этого метода, и каков гарантированный результат вызова метода. Например. в контракте может указываться, что не ожидаются параметры null, и если метод передан параметр null, он будет бросать NullPointerException. Хорошими примерами таких контрактов являются Javadoc методов в рамках Collection.

Обратите внимание, что некоторые языки допускают или даже требуют формального определения контрактов, поэтому контракты компилируются в код и активно внедряются во время выполнения. Eiffel - такой язык. Однако у Java нет такого средства; контракты, определенные в Javadoc, не являются формальными, для них не существует даже строгого формата. Они предназначены только для чтения человеком, оставленного незамеченным JVM. Таким образом, нарушение контракта на Java может быть не сразу заметным, только позже, когда появляются возникающие ошибки.

Контракты могут быть определены как для конкретных методов класса, так и для абстрактных/интерфейсных методов. Контракт интерфейса (должен быть) привязан ко всем его реализациям. То есть HashSet.add, TreeSet.add, LinkedHashSet.add и т.д. все должны выполнять контракт Set.add (и могут дополнительно уточнить его). Реализация, которая не ведет себя согласно контракту Set.add, нарушает принцип подписи Лискова.

Ответ 3

Насколько я знаю, расширенные классы должны иметь те же методы, которые определены суперклассом. Что касается различий между методами добавления, я предлагаю сравнить javadocs для соответствующего add() s