<aside> 💡 상속은 코드를 재사용하는 강력한 수단이지만, 항상 최선은 아니다!
</aside>
상위 클래스와 하위 클래스를 모두 같은 프로그래머가 통제하는 패키지 안이라면 안전하다.
메서드 호출과 달리 상속은 캡슐화를 깨뜨린다.
public class InstrumentedHashSet<E> extends HashSet<E> {
private int addCount = 0;
public InstrumentedHashSet() {
}
public InstrumentedHashSet(final int initCap, final float loadFactor) {
super(initCap, loadFactor);
}
@Override
public boolean add(final E e) {
addCount++;
return super.add(e);
}
@Override
public boolean addAll(final Collection<? extends E> c) {
addCount += c.size();
return super.addAll(c);
}
public int getAddCount() {
return addCount;
}
}
addAll 메서드로 원소 3개를 인스턴스에 더했다고 해보자.InstrumentedHashSet<String> s = new InstrumentedHashSet<>();
s.addAll(List.of("틱", "틱틱", "펑"));
HashSet 의 addAll 은 각 원소를 add 메서드를 호출해 추가하는데, 이 때 불리는 add 는 InstrumentedHashSet 에서 재정의된 메서드이다.addCount 에 값이 중복해서 더해진 것.→ 하위 클래스에서 addAll 메서드를 재정의하지 않거나, 다른 식으로 재정의하면 해결할 수 있다.
private 필드를 써야 한다면 구현 자체가 불가능하다.하위 클래스가 깨지기 쉬운 이유는 또 존재한다.
Hashtable 과 Vector 를 컬렉션 프레임워크에 포함시키자, 관련된 보안 구멍을 다 수정해야 했었다.<aside> 💡 다행히, 이상의 문제들을 모두 피할 수 있다! → 컴포지션(composition : 구성)
</aside>
private 필드로 기존 클래스의 인스턴스를 참조하게 하자.