티스토리 뷰

이번에는 상속에 대해 공부해보겠습니다. 상속은 일반적으로 자식이 부모로부터 재산을 물려받는 것을 의미하죠.

스타크래프트에는 공격을 할 수 없는 유닛도 있다고 설명 드렸는데, 부상당한 유닛을 치료해주는 메딕이 그 대표적인 예입니다.

 

메딕과 같이 공격력이 없는 유닛은 AttackUnit 클래스로 생성하기에는 알맞지 않으니, 이전에 만들었던 Unit 클래스를 다시 가져와보겠습니다. AttackUnit 클래스에 공격력을 의미하는 damage 멤버 변수가 있으므로 Unit 클래스는 공격 가능 여부와 상관 없이 일반적인 유닛을 위한 클래스로 수정을 해보겠습니다.

class Unit:
    def __init__(self, name, hp, damage): # 공격력인 damage 제외
        self.name = name
        self.hp = hp
        self.damage = damage # 제외
        print("{0} 유닛이 생성되었습니다.".format(self.name)) # 제외
        print("체력 {0}, 공격력 {1}".format(self.hp, self.damage)) # 제외

모든 유닛은 이름과 체력 정보는 가지기 때문에 name, hp 는 남겨두고 공격력인 damage 는 없애보겠습니다. 코드를 간결하게 하기 위해 print() 부분도 제외하겠습니다.

 

마치 다이어트를 한 것처럼 코드가 많이 가벼워졌네요!

# 일반 유닛
class Unit:
    def __init__(self, name, hp):
        self.name = name
        self.hp = hp

 

앞장에서 만든 AttackUnit 클래스도 다시 한 번 살펴볼까요?

# 공격 유닛
class AttackUnit:
    def __init__(self, name, hp, damage):
        self.name = name
        self.hp = hp
        self.damage = damage

    def attack(self, location):
        print("{0} : {1} 방향으로 적군을 공격 합니다. [공격력 {2}]" \
            .format(self.name, location, self.damage))

    def damaged(self, damage):
        print("{0} : {1} 데미지를 입었습니다.".format(self.name, damage))
        self.hp -= damage
        print("{0} : 현재 체력은 {1} 입니다.".format(self.name, self.hp))
        if self.hp <= 0:
            print("{0} : 파괴되었습니다.".format(self.name))

 

Unit 클래스와 AttackUnit 클래스의 __init__() 생성자만 놓고 비교해보니 겹치는 부분이 있네요.

# 일반 유닛
class Unit:
    def __init__(self, name, hp):
        self.name = name
        self.hp = hp
        
# 공격 유닛
class AttackUnit:
    def __init__(self, name, hp, damage):
        self.name = name
        self.hp = hp
        self.damage = damage
        
    ... # 메소드 생략

 

일반 유닛도 name, hp 를 가지고 공격 유닛도 name, hp 를 가집니다. 만약 Unit 의 성격에 따라 공격 유닛, 공중 유닛, 공중 공격 유닛 등 수많은 클래스로 확장이 된다면 매 클래스마다 name, hp 를 일일이 적어주어야 되겠죠. 

 

다행히 클래스에는 상속이라는 개념이 있어서 공통되는 부분은 코드를 중복으로 적지 않고도 재사용을 할 수 있습니다.  AttackUnit 클래스는 Unit 클래스의 name, hp 멤버변수를 포함하면서 추가로 damage 멤버변수를 정의하고 있으므로 Unit 클래스로부터 상속을 받으면 Unit 클래스의 name, hp 를 그대로 사용할 수 있게 됩니다.

 

클래스를 상속받을 때는 클래스 이름 뒤에 괄호를 적고 상속 받을 클래스 이름을 명시해주면 됩니다. 그리고 이 때 두 클래스는 자식클래스와 부모클래스라고 표현합니다. 마치 실생활에서 자식이 부모로부터 상속받는 것과 같이 말이죠.

class 자식클래스(상속받을 부모클래스):

그리고 코드를 재사용하기 위해 AttackUnit 클래스의 __init__() 생성자에서 name, hp 멤버변수를 정의하는 부분은 다음과 같이 부모 클래스의 __init__() 생성자를 호출하는 방식으로 코드를 간소화할 수가 있습니다. 이 때도 self 를 넘겨주는 것은 잊지 말아야 하지요.

# 공격 유닛
class AttackUnit(Unit): # Unit 클래스를 상속
    def __init__(self, name, hp, damage):
        Unit.__init__(self, name, hp) # 부모 클래스의 생성자 호출
        self.damage = damage
        
    ... # 메소드 생략

 

이렇게 하면 AttackUnit 클래스는 Unit 클래스의 모든 멤버변수와 메소드를 그대로 이용할 수 있으며 거기에 AttackUnit 만을 위한 멤버변수와 메소드를 추가로 확장할 수 있게 됩니다.

 

서로 관련 있는 클래스들은 이와 같이 공통적인 부분은 부모 클래스로 정의하고 자식 클래스에서는 필요한 부분을 확장하여 사용하면 불필요한 코드의 중복을 방지할 수 있고 변경이 필요한 경우에도 작업을 최소화할 수 있습니다.

 

상속을 적용하여 지금까지 작성된 전체 코드입니다.

# 일반 유닛
class Unit:
    def __init__(self, name, hp):
        self.name = name
        self.hp = hp

# 공격 유닛
class AttackUnit(Unit):
    def __init__(self, name, hp, damage):
        Unit.__init__(self, name, hp)
        self.damage = damage

    def attack(self, location):
        print("{0} : {1} 방향으로 적군을 공격 합니다. [공격력 {2}]" \
            .format(self.name, location, self.damage))

    def damaged(self, damage):
        print("{0} : {1} 데미지를 입었습니다.".format(self.name, damage))
        self.hp -= damage
        print("{0} : 현재 체력은 {1} 입니다.".format(self.name, self.hp))
        if self.hp <= 0:
            print("{0} : 파괴되었습니다.".format(self.name))

 

확인을 위해 앞 장에서 만들었던 파이어뱃 유닛 코드를 실행시켜서 동일한 실행 결과가 나오는지 보겠습니다.

# 파이어뱃 : 공격 유닛, 화염방사기. 
firebat1 = AttackUnit("파이어뱃", 50, 16) # 체력 50, 공격력 16
firebat1.attack("5시") # 5시 방향으로 공격 명령

# 공격 2번 받는다고 가정
firebat1.damaged(25) # 남은 체력 25
firebat1.damaged(25) # 남은 채력 0

 

Unit 클래스는 간소화되었고 AttackUnit 클래스는 Unit 클래스를 상속하도록 변경되었지만 부모 클래스로부터 물려받은 멤버 변수 hp, name 을 그대로 사용할 수 있기 때문에 실제 동작은 동일하게 실행되는 것을 확인할 수 있습니다.

파이어뱃 : 5시 방향으로 적군을 공격 합니다. [공격력 16]
파이어뱃 : 25 데미지를 입었습니다.
파이어뱃 : 현재 체력은 25 입니다. 
파이어뱃 : 25 데미지를 입었습니다.
파이어뱃 : 현재 체력은 0 입니다.
파이어뱃 : 파괴되었습니다.
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
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
글 보관함