Java: установить интерфейс и различия интерфейса коллекции - PullRequest
20 голосов
/ 20 октября 2010

Я только что посмотрел интерфейс 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.Я знаю это.Я просто спрашиваю, есть ли какая-то техническая разница (то есть с компилятором).То есть, говоря в общем:

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

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


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

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

Ответы [ 4 ]

11 голосов
/ 20 октября 2010

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

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

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

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

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

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

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

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

9 голосов
/ 20 октября 2010

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

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

6 голосов
/ 20 октября 2010

Метод имеет нечто большее, чем его подпись.

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

2 голосов
/ 20 октября 2010

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

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

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

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

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

...