PE Notes · SW
상속 vs 조합
is-a 계층의 상속과 has-a 위임의 조합을 결합·재사용 축으로 가르고, 상속을 써도 되는 두 원칙을 정리합니다.
코드를 한 줄도 안 늘리고 싶은 순간에 상속이 먼저 떠오릅니다. 부모의 메서드를 공짜로 받으니까요. 그 공짜는 부모와 자식을 같은 수명으로 묶습니다. 은 타입 계층이고, 은 부품을 품에 안는 일입니다.
is-a와 has-a
상속은 “자식은 부모다”를 컴파일러가 믿게 합니다. 다형성과 틀 메서드에 맞습니다. 대가는 깨지기 쉬운 기반 클래스입니다. 부모가 한 줄 바뀌면 자식 전부가 흔들립니다. 계층이 깊을수록 생성 순서와 숨은 의존이 커집니다.
조합은 “나는 이 부품을 가진다”입니다. 엔진을 필드로 두고 호출만 넘깁니다. 부품을 갈아 끼울 수 있고, 여러 역할을 동시에 품습니다. 다중 상속이 없는 언어에서 조합이 기본 재사용입니다.
| 비교축 | 상속 | 조합 |
|---|---|---|
| 관계 | is-a | has-a |
| 재사용 | 구현·인터페이스를 물려받음 | 위임으로 빌려 씀 |
| 결합 | 컴파일 시점, 강함 | 상대적으로 약함 |
| 유연 | 계층을 나중에 바꾸기 어렵다 | 부품 교체가 쉽다 |
| 위험 | 기반 클래스 취약, 계층 폭발 | 위임 코드가 늘 수 있다 |
GoF가 “조합을 상속보다 선호하라”고 한 이유는, 재사용 목적이 구현 복사일 때 상속이 과하기 때문입니다.
상속을 쓰는 두 원칙
첫째, 진짜 is-a여야 합니다. 자식 객체를 부모 자리에 넣어도 계약이 깨지지 않아야 합니다. 이것이 입니다. 정사각형을 직사각형 하위로 두면 면적 가정이 깨집니다. 이름이 비슷하다고 계층을 그리지 않습니다.
둘째, 구현을 재사용하려고 상속하지 않습니다. 공통 코드가 필요하면 그 코드를 부품으로 빼서 조합합니다. 타입이 필요한 자리에는 인터페이스 상속(계약만 물려받기)을 쓰고, 구현 상속은 틀 메서드처럼 안정된 뼈대에 한정합니다.
UI의 MVC가 컨트롤러를 한 부모에 쌓으면 거대 컨트롤러가 됩니다. 화면 행위는 조합으로 붙이는 편이 안전합니다.