[Python] 상속

3 minute read

[Python] 상속

Inflearn Study

링크: https://www.inflearn.com/

  • 인프런에서 “파이썬 무료 강의 (기본편) - 6시간 뒤면 나도 개발자” 강의를 들으며 혼자 공부한 내용입니다.

상속

  • 부모 클래스와 자식 클래스가 존재하며 부모 클래스의 멤버를 자식 클래스가 물려받을 수 있습니다.
# 일반 유닛
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): # self는 따로 보내줄 필요 없음
        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))
  • 상속 : class 클래스 이름 ( 상속 받을 클래스 이름 )
  • Unit.__init__(self, name, hp) : 명시적으로 Unit 클래스의 생성자를 호출하는 방법
    • 이 경우에는 self를 함께 전달해야 합니다.

다중 상속

  • 두 개 이상의 클래스를 상속 받는 것
    • 하나의 자식 클래스가 두 개 이상의 부모 클래스를 가지는 것
# 드랍쉽 : 공중 유닛, 수송기, 미린/ 파이어뱃/ 탱크 등을 수송 공격 기능 x
# 날 수 있는 기능을 가진 클래스
class Flyable:
    def __init__(self, flying_speed):
        self.flying_speed = flying_speed

    def fly(self, name, location):
        print("{0} : {1} 방향으로 날아갑니다. [속도 {2}]"\
            .format(name, location, self.flying_speed))

# 공중 공격 유닛 클래스
class FlyableAttackUnit(AttackUnit, Flyable):
    def __init__(self, name, hp, damage, flying_speed): # 생성자
        AttackUnit.__init__(self, name, hp, damage)
        Flyable.__init__(self, flying_speed)
        
# 발키리 : 공중 공격 유닛, 한 번에 14발 미사일 발사
valkyrie = FlyableAttackUnit("발키리", 200, 6, 5)
valkyrie.fly(valkyrie.name,"3시")    
  • AttackUnit.__init__(self, name, hp, damage) : 명시적으로 AttackUnit 클래스의 생성자를 호출하는 방법
  • Flyable.__init__(self, flying_speed) : 명시적으로 Flyable 클래스의 생성자를 호출하는 방법

다중 상속 시 주의해야할 점 (super 사용)

  • 다이아몬드 상속을 하는 경우
class Unit:
    def __init__(self): # 생성자
        print("Unit 생성자")

class UnitB(Unit):
    def __init__(self): # 생성자
        print("UnitB 생성자")
        Unit.__init__(self)

class UnitC(Unit):
    def __init__(self): # 생성자
        print("UnitC 생성자")
        Unit.__init__(self)

class UnitD(UnitB, UnitC):
    def __init__(self): # 생성자
        print("UnitB 생성자")
        UnitB.__init__(self)
        UnitC.__init__(self)
  • UnitD의 인스턴트 객체를 생성하면 UnitB와 UnitC에서 Unit의 클래스가 두 번 호출됩니다.
  • 이를 피하기 위해 super 라는 함수를 이용합니다.
    • super : 부모 클래스의 객체를 반환
class Unit:
    def __init__(self): # 생성자
        print("Unit 생성자")

class UnitB(Unit):
    def __init__(self): # 생성자
        print("UnitB 생성자")
        super.__init__(self)

class UnitC(Unit):
    def __init__(self): # 생성자
        print("UnitC 생성자")
        super.__init__(self)

class UnitD(UnitB, UnitC):
    def __init__(self): # 생성자
        print("UnitB 생성자")
        super.__init__(self)
  • Unit의 클래스가 두 번 호출되는 것을 막아 줍니다.

메소드 오버라이딩 (Method Overriding)

: 상속의 개념 중 하나로 자식 클래스가 자신의 부모 클래스들 중 하나에 의해 이미 제공된 메소드를 특정한 형태로 구현하는 것입니다.

# 일반 유닛
class Unit:
    def __init__(self, name, hp, speed): # 생성자
        self.name = name # 멤버 변수(클래스 내 생성된 변수)
        self.hp = hp
        self.speed = speed
    
    def move(self, location) :
        print("[지상 유닛 이동]")
        print("{0} : {1} 방향으로 이동합니다. [속도 {2}]"\
            .format(self.name, location, self.speed))
        
# 공격 유닛
class AttackUnit(Unit): # 상속
    def __init__(self, name, hp, speed, damage): # 생성자
        Unit.__init__(self, name, hp, speed)
        self.damage = damage
    
    def attack(self, location): # self는 따로 보내줄 필요 없음
        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))

# 드랍쉽 : 공중 유닛, 수송기, 미린/ 파이어뱃/ 탱크 등을 수송 공격 기능 x
# 날 수 있는 기능을 가진 클래스
class Flyable:
    def __init__(self, flying_speed):
        self.flying_speed = flying_speed

    def fly(self, name, location):
        print("{0} : {1} 방향으로 날아갑니다. [속도 {2}]"\
            .format(name, location, self.flying_speed))

# 공중 공격 유닛 클래스
class FlyableAttackUnit(AttackUnit, Flyable):
    def __init__(self, name, hp, damage, flying_speed): # 생성자
        AttackUnit.__init__(self, name, 0, hp, damage)
        Flyable.__init__(self, flying_speed)

    def move(self, location):
        print("[공중 유닛 이동]")
        self.fly(self.name, location)

# 벌쳐 : 지상 유닛, 기동성이 좋음
vulture = AttackUnit("벌쳐", 80, 10, 20)

# 배틀 크루저: 공중 유닛, 체력, 공격력 좋음
battlecruiser = FlyableAttackUnit("배틀크루저", 500, 25, 3)

vulture.move("11시")
battlecruiser.move("9시")
  • Unit 클래스의 move 함수를 FlyableAttackUnit 클래스에서 재정의 하고있습니다.
  • vulture.move(“11시”) 에서는 Unit 클래스의 move 함수대로 출력됩니다.
  • battlecruiser.move(“9시”) 에서는 FlyableAttackUnit 클래스의 move 함수로 출력됩니다.

pass

# 일반 유닛
class Unit:
    def __init__(self, name, hp, speed): # 생성자
        self.name = name # 멤버 변수(클래스 내 생성된 변수)
        self.hp = hp
        self.speed = speed
    
    def move(self, location) :
        print("[지상 유닛 이동]")
        print("{0} : {1} 방향으로 이동합니다. [속도 {2}]"\
            .format(self.name, location, self.speed))

# pass
# 건물
class BuildingUnit(Unit):
    def __init__(self, name, hp, location):
        pass # 아무것도 안하고 그냥 넘어갈거임

# 서플라이 디폿 : 건물, 1개 건물 = 8개 유닛
supply_depot = BuildingUnit("서플라이 디폿", 500, "7시")

def game_start():
    print("[알림] 새로운 게임을 시작합니다.")

def game_over():
    pass

game_start()
game_over()
  • pass : 실행할 코드가 없다는 것으로 다음 행동을 계속해서 진행합니다.
  • continue : 다음 순번의 loop를 강제로 돌도록 하는 것을 의미합니다.

Leave a comment