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
), которые имеют точно такую же документацию/контракт. Почему они также переоформлены?
Ответы
Ответ 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
, я не должен допускать дубликаты?