상속보다 합성을 먼저 고려해야 하는 이유
4강. 상속보다 합성을 먼저 고려해야 하는 이유
1. 이번 강의에서 해결할 문제
할인·알림 조합마다 자식 클래스를 만들면 계층이 폭발합니다. 이름상 is-a여도 자식이 부모의 전제 조건을 깨면 안전한 상속이 아닙니다.
2. 학습 목표
3. 핵심 개념
상속은 부모 계약을 모든 자식이 지킬 때 사용합니다. 재사용만 필요하면 has-a 합성을 우선합니다. 합성도 무조건 인터페이스일 필요는 없으며 변형이 하나라면 구체 값 멤버가 단순합니다.
상속은 “A는 B의 한 종류”라는 이름만으로 정하지 않습니다. 자식 객체를 부모가 필요한 모든 위치에 넣어도 부모의 사전 조건, 결과 약속과 오류 정책을 지켜야 합니다. 할인 종류 조합을 VipWeekendOrderService, CouponVipOrderService 같은 자식으로 계속 만들면 기능 수의 곱만큼 클래스가 늘어납니다.
합성은 OrderService가 할인 정책을 **소유하고 사용한다(has-a)**는 관계입니다. 서비스의 주문 책임은 유지하고 바뀌는 계산만 정책 객체로 교체합니다. 변형·테스트 대체가 실제로 필요할 때 인터페이스를 만들고, 하나의 고정 규칙뿐이면 정수 멤버나 구체 객체가 더 단순합니다.
4. 가장 작은 예제로 시작하기
아래 C++17 예제는 할인 정책 두 개를 같은 서비스에 주입해 결과를 비교합니다.
#include <algorithm>
#include <iostream>
#include <memory>
class DiscountPolicy {
public:
virtual ~DiscountPolicy() = default;
virtual int apply(int total) const = 0;
};
class NoDiscount final : public DiscountPolicy {
public:
int apply(int total) const override { return total; }
};
class FixedDiscount final : public DiscountPolicy {
int amount_;
public:
explicit FixedDiscount(int amount) : amount_(amount) {}
int apply(int total) const override {
return std::max(0, total - amount_);
}
};
class OrderService {
std::unique_ptr<DiscountPolicy> discount_;
public:
explicit OrderService(std::unique_ptr<DiscountPolicy> policy)
: discount_(std::move(policy)) {}
int checkout(int total) const { return discount_->apply(total); }
};
int main() {
OrderService normal{std::make_unique<NoDiscount>()};
OrderService event{std::make_unique<FixedDiscount>(200)};
std::cout << normal.checkout(1000) << '\n';
std::cout << event.checkout(1000) << '\n';
}
예상 출력:
1000
800
5. 코드가 동작하는 이유
OrderService는 구체 할인 이름을 모르고 DiscountPolicy::apply 계약만 호출합니다. unique_ptr는 서비스 하나가 정책 하나를 소유한다는 뜻이고 가상 소멸자는 기반 포인터로 자식 객체를 안전하게 파괴하게 합니다.
변경 전 상속 트리에서는 새 할인 조합마다 서비스 자식과 여러 조건문을 수정할 수 있습니다. 변경 후에는 새 정책 클래스를 추가하고 조립 지점에서 선택하면 기존 주문 흐름은 그대로입니다. 다만 할인 규칙이 영원히 하나라면 이 계층 대신 int discountAmount_가 더 낫습니다.
6. 자주 하는 실수와 해결법
7. 직접 실습
8. 이해 점검 질문 3개
9. 핵심 요약
10. 다음 강의 연결
교체 가능한 협력을 합성했습니다. 다음 강의에서는 호출자가 필요한 최소 역할만 인터페이스로 표현합니다.
상속보다 합성을 먼저 고려해야 하는 이유 미니 퀴즈
선택 즉시 정답과 해설을 확인할 수 있습니다. 결과는 이 브라우저에만 저장됩니다.
학습을 마쳤나요?
직접 실습과 점검 질문까지 확인한 뒤 완료로 표시하세요.