Подтвердить что ты не робот

Java: установка интерфейса и различия в интерфейсе коллекции

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

Например, Set переопределяет это:

/**
 * Returns the number of elements in this set (its cardinality).  If this
 * set contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
 * <tt>Integer.MAX_VALUE</tt>.
 *
 * @return the number of elements in this set (its cardinality)
 */
int size();

/**
 * Returns <tt>true</tt> if this set contains no elements.
 *
 * @return <tt>true</tt> if this set contains no elements
 */
boolean isEmpty();

И объявление в Collection:

/**
 * Returns the number of elements in this collection.  If this collection
 * contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
 * <tt>Integer.MAX_VALUE</tt>.
 *
 * @return the number of elements in this collection
 */
int size();

/**
 * Returns <tt>true</tt> if this collection contains no elements.
 *
 * @return <tt>true</tt> if this collection contains no elements
 */
boolean isEmpty();

Это кажется мне слишком избыточным. Почему бы просто не определить интерфейс Set как:

public interface Set<E> extends Collection<E> {}

Я думаю, что нет никакой разницы между этими интерфейсами, верно?


Конечно, я не спрашиваю о различной семантике/значении Set. Я знаю это. Я просто спрашиваю, имеет ли это технически (т.е. Компилятору) какую-либо разницу. I., говоря вообще:

interface A { void foo(); }
interface B extends A { void foo(); }
interface C extends A {}

Теперь, есть ли разница между A, B или C?


В то время как контракт (то есть то, что сказано в документации) может действительно отличаться для некоторых функций (как для add), есть веская причина для их повторного использования: чтобы иметь возможность разместить новую документацию, то есть определить новый контракт.

Однако существуют также функции (например, isEmpty), которые имеют точно такую ​​же документацию/контракт. Почему они также переоформлены?

4b9b3361

Ответ 1

Технически для компилятора это не имеет никакого значения.

Однако набор не может иметь повторяющиеся записи, в то время как коллекция может. Об этом стоит знать.

Из-за этого семантика методов для параметров, возвращаемых значений и того, что происходит, может означать разные вещи. Redeclaring также позволяет javadoc стать более конкретным. Например, для add():

Set: @return true, если этот набор еще не содержит указанный элемент

Коллекция: @return true, если этот набор изменился в результате вызова

Значение для множества более конкретно.

Даже для методов, которые не являются более конкретными, это позволяет javadoc быть более приятным. Например, для size(): "Возвращает количество элементов в этом наборе (его мощность)". который ближе к языку, который люди, привыкшие к математическим наборам, поймут.

В документах API сводятся к следующему: "Интерфейс Set устанавливает дополнительные условия, помимо тех, что унаследованы от интерфейса Collection, от контрактов всех конструкторов и контрактов методов add, equals и hashCode. для других унаследованных методов также включены здесь для удобства (спецификации, сопровождающие эти объявления, были адаптированы к интерфейсу Set, но они не содержат никаких дополнительных условий).

Ответ 2

Ответ представлен в API java6 для набора.

"Интерфейс Set устанавливает дополнительные условия, помимо тех, которые унаследованы из интерфейса Collection, в контрактах всех конструкторов и контрактах методов add, equals и hashCode. Объявления для других унаследованных методов также включены здесь для удобства. (Спецификации, прилагаемые к этим объявлениям, были адаптированы к интерфейсу Set, но они не содержат никаких дополнительных условий.)"

Ответ 3

Существует больше метода, чем его подпись.

В этом случае документация этих методов была адаптирована к наборам с точки зрения пред- и пост-условий и терминологии.

Ответ 4

Они переопределяются, потому что, даже если имена одинаковы, они имеют разное значение. Метод add в Set является конкретной реализацией общего метода add в Collection.

Цель состоит в том, чтобы явно указать, что метод add os Set сильно отличается от метода добавления Collection.

Почему бы просто не определить интерфейс Set как:

public interface Set<E> extends Collection<E> {} 

Если бы это было сделано таким образом, не было бы места, где можно указать контракт Set. Как я узнаю, что, реализуя метод add для Set, я не должен допускать дубликаты?