2013-07-10 3 views
2

Я всегда видел, как структуры данных данных создаются как дочерние экземпляры и объявляются их родительскими интерфейсами. Например.Объявить как родительский интерфейс и инициализировать как дочерний экземпляр

Set<E> collection1 = new HashSet<E>(); 
Map<E> collection1 = new HashMap<E>(); 

В чем причина этого. Детские классы наследуют все методы, и все методы, упомянутые в документации Java из дочерних классов, переопределяются, но имеют одинаковое значение. Тогда в чем причина их объявления - их родительский интерфейс.

Любые входы значительно помогут мне в укреплении моих основ.


EDIT

Спасибо за Ваш отзыв. Я понимаю. Но в изменении

Set<E> collection1 = new HashSet<E>(); 

в

Set<E> collection1 = new LinkedHashSet<E>(); 

мы потеряем нашу ссылку на наш оригинальный HashSet как мы объявляем новый LinkedHashSet для эталонного набора. Так в чем смысл этого? Если бы мы могли применить старую реализацию к новой, не теряя данные, тогда это имело бы смысл.

ответ

4

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

Set<E> collection1 = new LinkedHashSet<E>(); 

Любой метод или код, ожидающий тип интерфейса, может быть снабжен любым его типом реализации.

Согласно Эффективное Java 2-е издание, пункт 52: Обратитесь к объектам их интерфейсов

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

Это то, что Liskov substitution principle говорит:

подставляемость принцип объектно-ориентированного программирования. В нем указано, что в компьютерной программе, если S является подтипом T, то объекты типа T могут быть заменены объектами типа S (т. Е. Объекты типа S могут быть заменены на объекты типа T) без изменения любого из желательные свойства этой программы (правильность, выполняемая задача и т. д.).

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

+0

Вероятно, стоит отметить, лежащую в основе реализации также упоминаются как «конкретная реализация», а также. – Durandal

+0

@MagicMan Отметил :) – NINCOMPOOP

1

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

В этом является хорошей практикой программирования, так как это уменьшает сцепление.

он официально известен как Liskov substitution principle.