Python 기초

클래스 관계

상속은 is-a 관계

상속에서 자식 클래스와 부모 클래스는 is-a 관계가 성립됩니다. is-a 관계는 "A는 B이다." 관계입니다.

따라서 상속의 계층 구조를 올바르게 설계하였는지를 알려면 is-a 관계가 성립하는지를 생각해보면 됩니다.

  • 김봉민은 알콜 중독자이다. (Kim BongMin is an Alcoholic.)
    • 자식 클래스는 Kim BongMin, 부모 클래스는 Alcoholic 입니다.
  • 레드벨벳은 우주 최강 아이돌이다. (Red Velvet is the strongest idol in the universe.)
    • 자식 클래스는 Red Velvet, 부모 클래스는 the strongest idol in the universe 입니다.

 

만약 "~은 ~을 가지고 있다"와 같은 has-a(포함) 관계가 성립되면 이 관계는 상속으로 모델리을 하면 안 됩니다. 예를 들어 아래와 같습니다.

  • 김봉민은 술을 가지고 있다. (Kim BongMin has a drink.)
  • 레드벨벳은 많은 팬들을 보유하고 있다. (Red velvet has a lot of fans.)

 

has-a 관계

객체지향 프로그래밍에서 has-a 관계는 구성 관계(composition) 또는 집합 관계(aggregation)를 의미합니다.

구성 관계에서는 하나의 객체가 다른 객체의 부품이 됩니다. 집합 관계에서는 하나의 객체가 다른 객체를 소유하게 됩니다. UML 다이어그램으로 그리면 아래와 같습니다.

uml car carburetor에 대한 이미지 검색결과

 

상단 그림에서 자동차는 카뷰레타를 가지고 있습니다. 검정색 다이아몬드 표시는 구성(composition)을 나타냅니다.

자동차가 카뷰레타로 구성되었다고 생각하여도 됩니다. 하단 그림에서 연못을 오리를 가지고 있습니다. 이때는 다이아몬드가 흰색인데 이것은 집합(aggregation)을 의미합니다.

집합은 다이아몬드가 있는 객체가 다른 객체를 소유하고 있다는 것을 의미합니다. 다이아몬드 옆의 숫자는 개수를 의미합니다.

오리에 붙은 0..* 은 연못이 오리를 0개에서 무한대 개수까지 가질 수 있다는 것을 의미합니다.

 

has-a 관계가 성립되는 경우에는 상속을 이용하는 것이 아니라 하나의 클래스 안에 다른 클래스의 객체를 포함시키면 됩니다.

is-a 관계 못지않게 has-a 관계를 이해하는 것도 중요합니다. 아주 간단한 예제를 들어보면 다음과 같습니다.

class Animal(object):
    pass    # 구체적인 코드를 적고 싶지 않을 때 pass를 사용합니다.

class Dog(Animal):
    def __init__(self, name):
        self.name = name

class Person(object):
    def __init__(self, name):
        self.name = name
        self.pet = None     # Person 객체의 인스턴스 변수 pet에 Dog 객체의 참조값을 저장합니다.

dog1 = Dog("봉민이네 개")
person1 = Person("김봉민")
person1.pet = dog1

 

위의 코드는 아주 간단하지만 is-a 관계와 has-a 관계가 동시에 들어 있습니다 .Dog 클래스와 Animal 클래스의 관계는 is-a 관계입니다. 하지만 Person 클래스와 Dog 클래스의 관계는 has-a 관계가 됩니다.

has-a 관계에서는 하나의 클래스 안에 다른 클래스를 가리키는 변수가 포함되고 여기에 실체 객체가 생성되어서 대입됩니다.

 

도전 과제

has-a 관계가 가장 쉽게 이해되는 예제 중의 하나가 카드(Card)와 덱(Deck) 입니다. 카드 게임장에 가서 보면 카드는 항상 덱 안에 들어 있습니다.

카드를 나타내는 Card 클래스를 작성하고 52개의 Card 객체를 가지고 있는 Deck 클래스를 작성합니다.

각 클래스의 __str__() 메소드를 구현하여서 덱 안에 들어 있는 카드를 출력합니다.

 

<실행 결과>

['♣ A', '♣ 2', '♣ 3', '♣ 4', '♣ 5', '♣ 6', '♣ 7', '♣ 8', '♣ 9', '♣ 10', '♣ J', '♣ Q', '♣ K', '◆ A', '◆ 2', '◆ 3', '◆ 4', '◆ 5', '◆ 6', '◆ 7', '◆ 8', '◆ 9', '◆ 10', '◆ J', '◆ Q', '◆ K', '♥ A', '♥ 2', '♥ 3', '♥ 4', '♥ 5', '♥ 6', '♥ 7', '♥ 8', '♥ 9', '♥ 10', '♥ J', '♥ Q', '♥ K', '♠ A', '♠ 2', '♠ 3', '♠ 4', '♠ 5', '♠ 6', '♠ 7', '♠ 8', '♠ 9', '♠ 10', '♠ J', '♠ Q', '♠ K']