티스토리 뷰

이펙티브 자바 Effective Java 2/E
국내도서
저자 : 조슈아 블로크(Joshua Bloch) / 이병준역
출판 : 인사이트 2014.09.01
상세보기

상속은 코드 재사용을 돕는 강력한 도구지만, 항상 최선이라고 할 수 없다.

메서드 호출과 달리, 상속은 캡슐화 원칙을 위반한다.
=> 하위 클래스가 정상 동작하기 위해서는 상위 클래스의 구현에 의존할 수 밖에 없다.

예제 클래스로 HashSet 클래스의 성능을 높이기 위해서 얼마나 요소가 추가되는지 확인하는 클래스를 작성해 본다.

//계승을 잘못 사용한 사례 public class InstrumentedHashSet<E> extends HashSet<E> { //요소를 삽입하려 한 횟수 private int addCount = 0; public InstrumentedHashSet() { } pulbic InstrmentedHashSet(int initCap, float loadFactor) { super(initCap, loadFactor); } @Override public boolean add(E e) { addCount++; return super.add(e); } @Override public boolean addAll(Collection<? extends E> c) { addCount += c.size(); return super.addAll(c); } public int getAddCount() { return addCount; } }

괜찮아 보이지만 제대로 동작하지 않는다.

InstrumentedHashSet<String> s = new InstrumentedHashSet<String>(); s.addAll(Arrays.asList("snap", "Cracle", "Pop"));

3을 반환해야 할 것 같지만 6을 반환하다.
HashSet의 addAll 메서드는 add 메서드로 구현되어 있기 때문이다.

public boolean addAll(Collection<? extends E> c) { boolean modified = false; for (E e : c) if (add(e)) modified = true; return modified; }

이런 문제로 인해서 override 한 addAll 메서드를 수정하더라도 이 fix는 상위 클래스 addAll에 의존해버린다. 만약 상위 클래스 addAll 메서드가 수정되어 더이상 add 메서드를 호출하지 않는다면 또 다시 하위 클래스 구현이 깨져버릴 것이다.

또 다른 하위 클래스 구현을 망치는 요인은 상위 클래스에 새로운 메서드가 추가될 경우이다.

위에 2가지 문제를 해결하는 방법은 새로운 클래스에 기존 클래스 객체를 참조하는 private 필드를 하나 두는 것이다. 이런 설계 기법을 구성(composition) 이라고 부르는데, 기존 클래스가 새 클래스의 일부가 되기 때문이다.

public class InstrumentSet<E> extends ForwardingSet<E> { private int addCount = 0; public InstrumentSet(Set<E> s) { super(s); } @Override public boolean add(E e) { addCount++; return super.add(e); } @Override public boolean addAll(Collection<? extends E> c) { addCount += c.size(); return super.addAll(c); } public int getAddCount() { return addCount; } }
public class ForwardingSet<E> implements Set<E> { private final Set<E> s; public ForwardingSet(Set<E> s) { this.s = s; } public boolean add(E e) { return s.add(e); } public boolean addAll(E e) { return s.addAll(e); } ... }

ForwardingSet 이라는 클래스가 Set 의 기능들을 전달(Forwarding)해주기 때문에 안정적이고 유연성이 높다. 또한 InstrumentedSet에 새로운 기능을 추가하기에도 용이하다

....


공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함