티스토리 뷰
항목 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
- 패턴
- DLL
- Effective c++
- 외돌개
- PowerShell
- 울릉도
- 서귀포블루버블
- Windows
- 암호화
- 제주도
- 스쿠버 다이빙
- 서귀포
- CMake
- Linux
- 성산블루버블
- 현포다이브
- 스쿠버다이빙
- OpenSource
- C++
- Build
- script
- C#.NET
- C# 고급 기술
- C
- 블루버블
- C#
- 네트워크 정보
- 블루버블다이브팀
- effective
- 블루버블다이빙팀
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |