/** * {@inheritDoc} * * <p>This implementation iterates over the specified collection, and adds * each object returned by the iterator to this collection, in turn. * * <p>Note that this implementation will throw an * <tt>UnsupportedOperationException</tt> unless <tt>add</tt> is * overridden (assuming the specified collection is non-empty). * * @throws UnsupportedOperationException {@inheritDoc} * @throws ClassCastException {@inheritDoc} * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} * @throws IllegalStateException {@inheritDoc} * * @see #add(Object) */ publicbooleanaddAll(Collection<? extends E> c) { booleanmodified=false; for (E e : c) if (add(e)) modified = true; return modified; }
위에 코드에서 보면 내부적으로 add 메소드를 다시 호출하고 있다 그래서 실행 코드가 6이 나왔다.
이렇게 상위클래스에 메소드으 모든 내용을 확인하고 커버 가능하면 메소드 재정의가 가능하지만 하기 어렵다. 위에코드에서 해법으로는 addAll을 다시 재정의 하면되지만 문제가 생길때 마다. 재정의 하기 힘들다.
또 다른방법으로 하위클래스가 깨지기 쉬운이유는 다음 릴리즈일때 상위클래스에 새로운 메소드가 추가 되면 깨지기 쉽다.
그래서 컴포지션을 사용하는 방법이 있다. 위에 코드를 컴포지션과 전달 방식으로 다시 구현한 코드이다.
// The wrapper is intended to count changes, // but those changes which are invoked from // Controller are just skipped publicvoidmakeChange(){ model.makeChange(); changesMade++; System.out.println(changesMade); } }
// Here the wrapper just fails to count changes, // because it does not know about the wrapped object // references leaked publicvoiddoChanges(){ System.out.println("나다 나다"); model.makeChange(); } }