상속(is-a 관계)
부모 클래스와 자식 클래스 사이의 의존성은 컴파일타임에 결정
부모 클래스의 코드를 재사용
클래스 사이의 높은 결합도
합성(has-a 관계)
두 객체 사이의 의존성은 런타임에 결정
객체의 퍼블릭 인터페이스에 의존
객체 사이의 낮은 결합도
상속을 남용했을 때 직면할 수 있는 세가지 문제
불필요한 인터페이스 상속 문제 : 자식 클래스에게 부적합한 부모 클래스의 오퍼레이션이 상속되므로 자식 클래스의 인스턴스의 상태가 불안정해짐
메서드 오버라이딩의 오작용 문제 : 자식 클래스가 부모 클래스의 메서드를 오버라이딩할 때 자식 클래스가 부모 클래스의 메서드 호출 방법에 영향을 받음
부모 클래스와 자식 클래스의 동시 수정 문제 : 부모 클래스와 자식 클래스 사이의 개념적인 결합으로 인해 부모 클래스를 변경할 때 자식 클래스도 함께 변경해야 함
상속을 합성으로 변경하기
자식 클래스에 선언된 상속 관계를 제거하고 부모 클래스의 인스턴스를 자식 클래스의 인스턴스 변수로 선언
상속으로 인한 조합의 폭발적인 증가
상속으로 인해 결합도가 높아지면 코드를 수정하는 데 필요한 작업의 양이 과도하게 늘어나는 경향이 있음
- 하나의 기능을 추가하거나 수정하기 위해 불필요하게 많은 수의 클래스를 추가하거나 수정해야 한다
- 단일 상속만 지원하는 언어에서는 상속으로 인해 오히려 중복 코드의 양이 늘어날 수 있다
OCP를 만족하는 설계를 만들 수 있는 한가지 방법은 부모 클래스에 새로운 추상 메서드를 추가하고 부모 클래스의 다른 메서드 안에서 호출하는 것
- 추상 메서드의 단점은 상속 계층에 속하는 모든 자식 클래스가 추상 메서드를 오버라이딩해야 한다는 것
- 훅 메서드 : 추상 메서드와 동일하게 자식 클래스에서 오버라이딩할 의도로 메서드를 추가했지만 편의를 위해 기본 구현을 제공하는 메서드
클래스 폭발 문제 또는 조합의 폭발 문제 : 상속의 남용으로 하나의 기능을 추가하기 위해 필요 이상으로 많은 수의 클래스를 추가해야 하는 경우
합성 관계로 변경하기
구현이 아닌 퍼블릭 인터페이스에 대해서만 의존할 수 있기 때문에 런타임에 객체의 관계를 변경할 수 있음
- 상속은 조합의 결과를 개별 클래스 안으로 밀어 넣는 방법
- 합성은 조합을 구성하는 요소들을 개별 클래스로 구현한 후 실행 시점에 인스턴스를 조립하는 방법을 사용하는 것
컴파일타임 의존성과 런타임 의존성의 거리가 멀어질수록 설계의 복잡도가 상승해서 코드를 이해하기는 어려워짐(적절한 트레이드오프가 있어야함)
믹스인
객체를 생성할 때 코드 일부를 클래스 안에 섞어 넣어 재사용하는 기법
- 컴파일 시점에 필요한 코드 조각을 조합하는 재사용 방법
'책 > Object' 카테고리의 다른 글
서브클래싱과 서브타이핑 (0) | 2020.08.25 |
---|---|
다형성 (0) | 2020.08.10 |
상속과 코드 재사용 (0) | 2020.07.27 |
유연한 설계 (0) | 2020.07.13 |
의존성 관리하기 (0) | 2020.07.06 |