상속과 합성 차이
객체지향 프로그래밍에서 상속과 합성은 자주 사용되는 재사용 기법 입니다. 코드 중복을 제거 하므로 나중에 코드 수정 및 확장을 더 쉽게 용이하게 관리 하기 위함 입니다.
상속(Inheritance) | 합성(Composition) |
---|---|
부모 클래스와 자식 클래스 사이의 의존성은 컴파일 타임에 해결 | 두 객체 사이의 의존성은 런타임에 해결 |
is-a 관계 | has-a 관계 |
부모클래스의 구현에 의존 결합도가 높음 | 구현에 의존하지 않음.내부에 포함되는 객체의 구현이 아닌 인터페이스에 의존 |
클래스 사이의 정적인 관계 | 객체 사이의 동적인 관계 |
부모 클래스 안에 구현된 코드 자체를 물려 받아 재사용 | 포함되는 객체의 퍼블릭 인터페이스를 재사용 |
상속(Inheritance) 의 경우는 부모 클래스 하고 자식 클래스를 상속 관계로 연결해서 자식 클래스가 부모 클래스에 선언한 코드를 재사용하고 있습니다.
반면 합성(Composition) 경우는 전체를 표현하는 객체가 부분을 표현하는 객체를 포함해서 부분 객체의 코드를 재사용 하게 됩니다.
상속 경우에는 부모클래스와 자식 클래스 사이에 의존성은 컴파일 타임에 결정 되지만 합성 경우 두 객체 사이 런타임 시점에 해결된다는 것이 차이가 있습니다.
그래서 상속은 ‘is-a 관계’ 반면 합성은 ‘has-a 관계’ 라고 지칭 합니다.
그런데 상속 경우 재사용 할 수 있는 부분에 있어서 부모 클래스가 정의한 코드를 쉽게 자식 클래스가 재정의 하는데 있어서 기존 코드를 쉽게 확장 할 수 있다는 큰 장점을 가지고 있지만
자식 클래스 입장에서 볼때 부모 클래스의 내부 구현을 상세히 알아야 하고 이 때문에 서로 결합도가 강하다는 것이 단점이 있습니다.
합성 경우는 구현에 의존하지 않기 때문에 상속의 단점을 극복이 가능 합니다. 즉 합성 경우는 내부에 포함되는 객체의 구현이 아닌 퍼블릭 인터페이스에 의존하기 때문 입니다.
따라서 상속 대신 합성을 이용하면 포함된 객체의 내부 구현이 변경 되더라도 영향을 최소화 할 수 있어서 변경에 있어서 더 안정적인 코드를 얻을 수 있습니다.
문자 타입 정책에 따른 문자 상세 내용 정책 조합하기
어느 전기차 판매 하고 있는 기업이 있습니다. 잠재 고객들에게 문자 메시지를 전송 통해 상품을 홍보 할려고 합니다.
지금 현재 문자 메시지 종류가 2가지가 있습니다.
문자 타입 정책
- 상품 홍보
- 상품 구입 안내
두가지 문자 타입 통해 고객들에게 문자 메시지를 전송 할 예정입니다. 이 두가지 문자 타입 정책 중 한가지를 선택해서 문자 메시지를 전송 하는 것이고
“문자 상세 내용 정책” 통해 문자 메시지를 내용을 첨부 및 조합을 이용해서 문자 메시지를 전송 하게 됩니다.
- 상품 설명 안내
- 상품 할인 적용 안내
예를들어 문자 타입 정책 중 ‘상품 홍보’ 를 선택하고 ‘문자 상세 내용 정책’ 에서 선택하지 않고 문자 메시지를 전송 할 수 있고
‘상품 설명 안내’ 만 선택해서 전송 할 수 있고 ‘상품 설명 안내’ 그리고 ‘상품 할인 적용 안내’ 내용을 조합 해서 문자 메시지를 전송 할 수 있습니다.
문자 메시지 전송 요구 사항
문자 메시지 전송시 필수 항목 ‘문자 타입 정책’ 을 선택 해야 합니다.
문자 타입 정책에서 ‘상품 홍보’, ‘상품 구입 안내’ 둘 중에 하나를 선택 해서 전송을 합니다.
문자 상세 내용 정책은 선택적으로 적용 가능
문자 타입 정책을 선택 했으면 문자 상세 내용 정책 중 ‘상품 설명 안내’, ‘상품 할인 적용 안내’ 선택 해서 전송 할 수 있고 선택을 하지 않아도 됩니다.
또한 조합 통해 전송 할 수 있어야 합니다.
문자 상세 내용 정책 선택시 임의 순서로 적용 가능
만약 문자 상세 내용 정책을 적용 한다면 ‘상품 설명 안내’ 및 ‘상품 할인 적용 안내’ 임의 순서로 조합 해서 문자 메시지를 전송 할 수 있어야 합니다.
상속 이용해서 문자 타입 정책 구현하기
지금까지 설명한 요구사항을 상속을 통해 문자 전송 메시지 정책을 구현 할려고 합니다.
1 | public abstract class SmsTypePolicy { |
‘문자 타입 정책’ 경우 SmsTypePolicy 추상 클래스를 부모를 삼아 상속 계층을 구현 해볼려고 합니다.
1 | public class PromotionType extends SmsTypePolicy { |
1 | public class PurchaseType extends SmsTypePolicy { |
‘SmsTypePolicy’ 추상 클래스로 구현하고 ‘PromotionType’ (상품 홍보), ‘PurchaseType’ (상품 구입 안내)
각각 smsMessageProcessing() 메소드를 구현 하도록 합니다.
‘문자 타입 정책’선택 후 ‘문자 상세 내용 정책’ 메시지 기능 조합하기
예를들어 문자 타입 정책 중 ‘상품 홍보’를 선택하고 문자 상세 내용 정책에서는 ‘상품 설명 안내’ 를 선택 해서 문자 메시지를 전송 하고자 한다고 하면
‘PromotionType’ 클래스를 이용해서 상속 받아 구현 합니다.
1 | public class GuidePromotionType extends PromotionType { |
부모 클래스의 메소드를 재사용 통해 활용 하고자 합니다. 재사용을 위해 ‘PromotionType’ 구현된 메시지를 가져올려고 super 사용 합니다.
이후 ‘상품 설명 안내’ 구현된 메시지와 조합 해서 SMS 문자 메시지를 가공 하도록 합니다.
1 | public class GuideAndDiscountPromotionType extends GuidePromotionType { |
예를들어 문자 타입 정책을 ‘상품 홍보’로 선택하고 문자 상세 내용 정책을 ‘상품 설명 안내’, ‘상품 할인 적용안내’ 2개의 상세 내용 정책을 조합해서
문자 메시지를 가공 할려고 합니다.
앞서 ‘GuidePromotionType’ (문자 타입 정책을 ‘상품 홍보’, 문자 상세 내용 정책을 ‘상품 설명 안내’) 클래스를 상속 받아
‘GuideAndDiscountPromotionType’ 클래스를 구현 하고자 합니다.
super 메소드를 이용해서 ‘GuidePromotionType’ 클래스의 ‘smsMessageProcessing’ 메소드를 호출해 가공된 문자 메시지를 가져오고
‘상품 할인 적용안내’ 관련 문자 메시지를 첨부 해서 최종 가공 처리 하게 됩니다.
‘상품 홍보’ -> ‘상품 설명 안내’ -> ‘상품 할인 적용 안내’ 에 대해 설명 했습니다. 요구 사항을 보면 문자 상세 내용 정책 선택시 임의 순서로 적용 가능 해야 합니다.
반대로 ‘상품 홍보’ -> ‘상품 할인 적용 안내’ -> ‘상품 설명 안내’ 적용 하고자 합니다.
1 | public class DiscountPromotionType extends PromotionType { |
1 | public class DiscountAndGuidePromotionType extends DiscountPromotionType { |
‘상품 홍보’ -> ‘상품 할인 적용 안내’ 방식으로 문자 메시지를 전송시에는 ‘DiscountPromotionType’ 클래스를 이용하면 됩니다.
‘상품 홍보’ -> ‘상품 할인 적용 안내’ -> ‘상품 설명 안내’ 구현시 ‘DiscountAndGuidePromotionType’ 클래스 통해 문자 메시지를 가공 합니다.
상속으로 인해 중복 코드 문제
앞서 이야기 한대로 ‘문자 타입 정책’은 두개 중 한개를 선택 해야 하고 ‘문자 상세 내용 정책’은 선택 할 수 있어야 하고 선택 안 할수도 있습니다.
그리고 선택시 여러 상세 내용 정책 중 순서 역시 임의로 결정 할수 있어야 합니다.
상속으로 이를 해결하고자 할때 모든 가능한 케이스를 모두 각각의 클래스로 재사용을 이용해 구현 해야 합니다.
‘GuideAndDiscountPromotionType’ 클래스 하고 ‘DiscountPromotionType’ 클래스의 Override 한 메소드 ‘smsMessageProcessing’ 확인 해봅시다.
중복 코드가 발생되었다는 것을 확인 할 수 있습니다.
자바 통해 상속을 구현시 단일 상속만 지원하기 때문에 중복 코드 문제 해결은 쉽지 않습니다.
상속으로 인한 클래스 폭발(class explosion)
지금까지 설명한 상속 계층을 문자 타입 정책과 문자 상세 내용 정책 조합 가능한 상속 계층을 나타나는 것 입니다.
만약에 여기서 문자 타입 정책 ‘상품 홍보’, ‘상품 구입 안내’ 에서 ‘상품 소개’ 이라는 문자 타입 정책을 추가 한다고 요구사항이 들어왔다고 하면
이와 같이 문자 타입 정책 추가으로 인해 ‘문자 상세 내용 정책’ 관련 구현체도 모두 구현도 해줘야 합니다. 하나의 기능을 추가 하기 위해 필요 이상으로 구현체를 만들어야 하는 경우를 ‘클래스 폭팔 (class explosion)’ 이라고 합니다.
이처럼 상속을 남용하게 되면 새롭게 만든 클래스에 하나의 기존의 기능을 연결하기 위해 상속을 하게 될꺼고 또 다시 새롭게 만든 클래스에 기능 연결하기 위해
상속을 하고 이렇게 필요 이상으로 많은 수의 클래스를 추가해야 합니다.
이러한 문제는 부모 클래스와 자식 클래스 사이에 강하게 결합하기 때문에 발생되는 부분 입니다.
Copyright 201- syh8088. 무단 전재 및 재배포 금지. 출처 표기 시 인용 가능.