티스토리 뷰
항목 38 ] “has – a(…는 …를 가짐)” 혹은 is – implemented-in-terms-of(…는 …를 써서 구현됨)”를 모형화할 때는 객체 합성을 사용하자
-=HaeJuK=- 2010. 3. 8. 10:27모형화할 때는 객체 합성을 사용하자
합성(composition)이란,
어떤 타입의 객체들이 그와 다른 타입의 객체들을 포함하고 있을 경우에 성립하는 그 타입들 사이의 관계를 일컫습니다.
포함된 객체들을 모아서 이들을 포함한 다른 객체를 합성한다는 뜻인데, 다음과 같은 경우입니다.
문제점
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | class Address { …. };     // 누군가의 거주지 class PhoneNumber { …. }; class Person { public: private:    std::string mane;  // 이 클래스를 이루는 객체 중 하나    Address address;   // 마찬가지    PhoneNumber voiceNumber;  // 역시 마찬가지    PhoneNumber faxNumber;  // 이것도 마찬가지 }; | cs | 
Person 객체는 string, Address와 PhoneNumber 객체로 이루어져 있습니다.
이런 경우를 두고 합성이라는 말을 사용하는데 다른 말로는 레이어링(layering), 포함(containment), 통합(addregetion), 내장(embedding)이라고도 합니다.
항목 32에서 public 상속의 의미가 “is – a(.. 는 … 의 일종이다)”라고 배웠습니다.
객체 합성 역시 의미를 갖고 있습니다.
실제 뜻이 2개나 되는데 2개인 이유는 소프트웨어 개발에서 대응하는 영역이 두 가지이기 때문입니다.
사물을 본뜬 사람, 이동수단, 비디오 프레임 등인데, 이런 객체는 소프트웨어의 응용 영역(application domain)에 속하고,
나머지들은 버퍼, 뮤 텍스, 탐색 트리 등 순수하게 시스템 구현만을 위한 인공물입니다.
이런 종류의 객체가 구현 영역(implementation domain)이라고 합니다.
여기서 객체 합성이 응용 영역의 객체들 사이에서 일어나면 has –a 관계입니다.
반면, 구현 영역에서 일어나면 is-implemented – in – terms – of 관계를 나타낸 것입니다.
위의 person 클래스는 has –a 관계입니다.
사람이 이름의 일종, 사람이 주소의 일종이라고는 말할 수 없는 것입니다.
그러나 사람이 이름을 가지며 사람이 주소를 가진다고 하는 것은 자연스럽습니다.
이렇기 때문에 is - a관계와 has - a관계의 역할을 헷갈리는 경우는 없습니다.
헷갈리는 부분은 is - a관계와 is – implemented – in – terms – of 관계의 차이점 일 것입니다.
한 예로, 객체로 구성된 작은 집합, 중복 원소가 없는 집합체를 나타내고 저장 공간도 적게 차치하는 클래스 템플릿이 필요하다고 했을 때,
표준 라이브러리의 set템플릿을 활용해 보기로 합니다.
set템플릿은 원소 한 개당 포인터 세 개의 오버헤드가 걸리도록 구현되어 있습니다.
그러므로 표준 라이브러리의 set템플릿은 적당하지 않습니다.
이번엔 list를 사용해보겠습니다.
이번 포인트는 set템플릿을 만들되 list에서 파생된 형태부터 시작되도록 만든다는 것입니다.
set <T>는 list <T>로부터 상속을 받습니다.
| 1 2 3 4 5 6 7 8 | // set을 만든답시고 list를 잘못 쓰는 방법 template<typename T> class set : public std::list<T>  { //…  }; | cs | 
항목 32의 설명에 따르면 D와 B 사이에 is - a관계가 성립하면 B에서 참인 것들이 전부 D에서도 참이어야 합니다.
하지만 list 객체는 중복 원소를 가질 수 있는 컨테이너입니다.
구현하고 싶은 건 중복된 원소가 있어서는 안 되는 겁니다.
이들 두 클래스 사이의 관계가 is – a가 될 리 없으므로, public 상속은 지금의 관계를 모형화하는 데 맞지 않습니다.
해결방법
set객체는 list 객체를 써서 구현되는 (is implemented in terms of) 형태의 설계가 가능하다는 것입니다.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | // set를 만드는 데 list를 제대로 쓰는 방법 template<class T> class set  { public:     bool member(const T& item) const;     void insert(const T& item);     void remove(const T& item);     std::size_t size() const; private:     std::list<T> rep;                         // set 데이터의 내부 표현부 }; template<typename T> bool set<T>::member(const T& item) const {     return set<T>::find(rep.begin(), rep.end(), item) != rep.end(); } template<typename T> void set<T>::insert(const T& item) {     if( !member(item) )     {         rep.push_back(item);     } } template<typename T> void set<T>::remove (const T& item) {     typename std::list<T>::iterator it = std::find(rep.begin(), rep.end(), item);     if ( it != rep.end() )     {         rep.erase(it);     } } template<typename T> std::size_t set<T>::size() const {     return rep.size(); } | cs | 
인라인 함수로 만들어도 될 정도의 구현입니다.
이 관계는 is – a가 아니라, is – implemented – in – terms – of입니다.
결론
객체 합성(composition)의 의미는 public 상속이 가진 의미와 완전히 다릅니다.
응용 영역에서 객체 합성의 의미는 has – a(… 는 …를 가짐)입니다.
구현 영역에서는 is – implemented – in – terms – of(… 는 …. 를 써서 구현됨)의 의미를 갖습니다.
- Total
- Today
- Yesterday
- 암호화
- 윈도우
- ReFS
- 블루버블다이빙팀
- 디자인패턴
- PowerShell
- 다이빙
- Thread
- 성산블루버블
- C
- 양파다이브
- 서귀포
- DLL
- C#
- RSA
- ip
- 패턴
- 현포다이브
- 리눅스
- 제주도
- C++
- 블루버블다이브팀
- Windows
- OpenSource
- Linux
- 울릉도
- 서귀포블루버블
- 스쿠버다이빙
- 블루버블
- Build
| 일 | 월 | 화 | 수 | 목 | 금 | 토 | 
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 | 
| 12 | 13 | 14 | 15 | 16 | 17 | 18 | 
| 19 | 20 | 21 | 22 | 23 | 24 | 25 | 
| 26 | 27 | 28 | 29 | 30 | 31 | 
