В примере в этой статье вы связаны с:
set.addAll(Arrays.asList("Snap", "Crackle", "Pop"));
Это вызывает InstrumentedHashSet.addAll
.
InstrumentedHashSet.addAll adds 3 to the counter, then calls
HashSet.addAll`.
HashSet.addAll
звонки this.add
три раза, чтобы добавить каждый из элементов.
Но this.add
действительно является вызовом для InstrumentedHashSet.add
!
Каждый звонок InstrumentedHashSet.add
добавляет 1 к счетчику и звонит super.add
.
Каждый вызов HashSet.add
выполняет фактическую работу по добавлению элемента в набор.
Конечным результатом является то, что мы добавили 6 к счетчику, а не 3, как вы ожидали.
Для правильной реализации InstrumentedHashSet
необходимо знать, как реализуется HashSet.addAll
, и НЕ увеличивать счетчик в addAll
. Но это знание нарушает инкапсуляцию. Подкласс не должен необходимо, чтобы знал, как реализован его суперкласс.
Может кто-нибудь объяснить, как состав избежать этой проблемы
Это позволяет избежать его, потому что, когда HashSet.addAll
вызовов this.add
, эти призывы к this.add
не призывают к InstrumentedHashSet.add
. Это прямые звонки на номер HashSet.add
.
Фактически, при условии, что HashSet.addAll
реализует договор Set.addAll
, не имеет значения InstrumentedHashSet
, как оно реализовано. Здесь нет нарушения инкапсуляции.
Обернутый 'HashSet' называет свой' add', а не 'add' оболочки. –