Python 강좌 / 상속과 합성: 코드를 재사용하는 방법
상속은 기존 클래스의 관계와 동작을 확장하는 방법이고 합성은 다른 객체를 구성 요소로 사용하는 방법입니다. 단순히 코드가 비슷하다는 이유보다 대체 가능한 관계인지, 바꾸어 끼울 협력인지로 선택해야 합니다.
관계와 변경 방향으로 판단하기
하위 객체가 상위 객체가 기대되는 곳에서도 약속을 지킬 수 있다면 상속을 검토할 수 있습니다. 장부가 할인 정책을 사용한다면 장부가 할인 정책의 한 종류는 아니므로 합성이 자연스럽습니다. 깊은 상속 계층은 변경 영향이 커질 수 있습니다.
관련 동작과 지원 조건은 상속과 합성: 코드를 재사용하는 방법 관련 공식 문서에서 확인할 수 있습니다.
super()는 부모 이름을 직접 고정하기보다 메서드 탐색 순서에 따라 다음 구현을 호출합니다. 다중 상속의 모든 규칙을 먼저 쓰기보다 단순한 구조에서 역할을 확인하세요.
전체 예제와 실행 결과
별도의 실습 폴더에서 아래 파일을 UTF-8로 저장합니다. 가상환경을 선택한 터미널에서 python composition.py 명령으로 실행합니다. macOS·Ubuntu에서 가상환경을 사용하지 않는 경우 명령 이름을 python3으로 바꿉니다.
composition.py 파일의 전체 내용입니다.
class FeePolicy:
def apply(self, amount):
return amount
class FixedFee(FeePolicy):
def __init__(self, fee):
self.fee = fee
def apply(self, amount):
return super().apply(amount) + self.fee
class Ledger:
def __init__(self, policy):
self.policy = policy
def charge(self, amount):
return self.policy.apply(amount)
print(Ledger(FeePolicy()).charge(8000))
print(Ledger(FixedFee(500)).charge(8000))
예상 결과는 다음과 같습니다.
8000 8500
상속과 합성이 함께 쓰인 부분
FixedFee는 FeePolicy의 apply 계약을 유지하며 결과 계산을 바꿉니다. Ledger는 정책 객체를 보관하고 계산을 위임합니다. 장부 코드를 바꾸지 않고 정책을 교체할 수 있으며 테스트에서도 작은 가짜 정책을 전달할 수 있습니다.
Python은 반드시 같은 부모 클래스를 상속해야만 이런 협력이 가능한 것은 아닙니다. apply 메서드를 제공하는 다른 객체도 사용할 수 있습니다. 필요한 인터페이스를 문서나 타입 힌트로 명확히 하는 것이 중요합니다.
구조를 바꾸기 전의 확인 질문
- 하위 클래스가 입력 조건을 더 까다롭게 만들거나 결과 의미를 바꾸지 않는가?
- 일부 기능만 필요해서 무관한 부모까지 상속하는 것은 아닌가?
- 구성 요소를 인수로 받아 교체하면 더 단순한가?
fixed fee를 0으로 바꿔 기본 정책과 같은 결과인지 확인합니다. 정책 내부에 입력·출력까지 섞지 않고 계산 결과를 반환하게 유지하면 상속과 합성의 선택 효과를 관찰하기 쉽습니다. 규모가 작다면 함수 하나로 표현하는 방안도 함께 비교합니다.




