(항목 18) 상속보다 구성 사용

이 글을 읽으면서 핵심 문구는 다음과 같을 것 같습니다.

“… 상속은 부모 클래스의 API ‘결함도’를 상속합니다.”

즉, 가능하면 상속을 사용하지 마십시오.

이 요소의 상속은 구현 상속을 참조합니다. (인터페이스 상속 x)

좋은 상속 사례

  • 슈퍼클래스와 서브클래스가 프로그래머에 의해 제어되는 패키지
  • 확장성을 위해 설계된 잘 문서화된 클래스입니다.

더 나쁜 상속

  • 다른 패키지의 구체적인 클래스가 다른 구체적인 클래스에서 상속되는 경우.

구현 상속 문제

재정의 방법

“… 슈퍼클래스 구현 방식에 따라 서브클래스가 다르게 동작할 수 있습니다.” 캡슐화 중단

“…하위 클래스에서 액세스할 수 없는 개인 필드를 사용해야 하는 경우 이 방법을 구현할 수 없습니다.”

하위 클래스에서 재정의하여 문제를 해결해도 상위 클래스가 변경되면 문제가 다시 발생합니다.

슈퍼클래스에 새 메서드 추가

“… 슈퍼클래스에 새로운 메소드가 추가되었는데 아쉽게도 서브클래스에 추가한 메소드와 동일한 시그니쳐를 가지고 있습니다.

반환 유형이 다르면 클래스가 컴파일되지 않습니다.”

“…아마도 수퍼클래스 방식에서 요구하는 계약을 충족하지 못할 것입니다.”

예 – 상속의 잘못된 사용)

기본 메서드에서 3개 항목이 포함된 목록을 추가했습니다.

출력 결과는 3이 아닌 6이었습니다.

public class InstrumentedHashSet<E> extends HashSet<E> {

    private int addCount = 0;

    public InstrumentedHashSet(){}

    public InstrumentedHashSet(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;
    }
}
public class Main {
    public static void main(String() args) {
        InstrumentedHashSet<String> s = new InstrumentedHashSet<>();
        s.addAll(List.of("틱", "탁탁", "펑"));

        System.out.println("======= 출력 =======");
        System.out.println(s.getAddCount());
    }
}

//출력결과
//6

HashSet의 슈퍼클래스

AbstractCollection 클래스에는 Collection 객체가 있는 만큼 add 메서드를 실행하도록 addAll 메서드를 작성한다.

우리가 작성한 CutomHashSet 클래스에서 총 6개의 추가를 수행하도록 add 메서드를 재정의했습니다.


대안

“…기존 클래스를 확장하는 대신 새 클래스를 만들고 전용 필드가 있는 이전 클래스의 인스턴스를 참조합니다.”

(기존에 구현된 클래스는 새로 생성되는 클래스의 컴포넌트로 사용됩니다.)

구성

“새 클래스의 인스턴스 메서드(비공개 필드에서 참조)는 이전 클래스의 해당 메서드를 호출하고 결과를 반환합니다.”

포워딩

“새로운 클래스의 방법”

전달 방법

구성과 전달의 조합을 가장 넓은 의미의 위임이라고 합니다.

새 클래스가 A에서 B를 상속해야 하는 경우

이것이 관계인지 스스로에게 물어보고 BA가 확실하다면 진행하십시오.

그렇지 않은 경우 구성을 사용하십시오!

추가 학습 콘텐츠

자체 사용, 래퍼 클래스, 데코레이션 패턴, 콜백 프레임워크,