본문 바로가기
프로그래밍/아키텍처 with python

[Architecture][Python]상속과 서브 클래스

by 우주를놀라게하자 2022. 5. 24.
반응형
SMALL

상속과 서브 클래스를 왜 사용해야 하는가?


클래스를 사용하는 이유는 효율적으로 데이터를 관리하고, 같은 코드의 반복을 없애고자 하는 DRY(Don't Repeat Yourself)의 개념이 담겨 있다. 상속 또한 한 번 정의한 데이터 타입을 필요에 따라서 수정하고 다시 재활용해서 반복되는 코드를 줄이고자 하는 목적을 가진다.

예제


스타크래프트 Unit을 가지고 예제 프로그램을 만들어 보려고 한다.

스타크래프트 상에는 다양한 Unit이 존재한다. 이때 매번 각 유닛에 대해서 클래스를 구성하여 유닛을 선언하는것은 비효율적이기 때문에,

Unit이라는 공통된 클래스를 선언하고, 그 하위에 내가 필요한 유닛들의 속성들을 추가하면서 확장성을 갖는 프로그램을 만들려고 한다.

lagacy 예제  - 1


class Unit(object):
    def __init__(self, rank, size, life):
        # 상속받는 클래스의 이름을 가져온다
        self.name = self.__class__.__name__
        self.rank = rank
        self.size = size
        self.life = life

    def show_status(self):
        print(f'이름: {self.name}')
        print(f'등급: {self.rank}')
        print(f'사이즈: {self.size}')
        print(f'라이프: {self.life}')

class Tank(Unit):
    def __init__(self, rank, size, life, attack_type):
        # 상속받는 클래스의 이름을 가져온다
        self.name = self.__class__.__name__
        self.rank = rank
        self.size = size
        self.life = life
        self.attack_type = attack_type

    def show_status(self):
        print(f'이름: {self.name}')
        print(f'등급: {self.rank}')
        print(f'사이즈: {self.size}')
        print(f'라이프: {self.life}')
        print(f'공격 타입: {self.attack_type}')


tank_1 = Tank('시즈탱크', 'Big', 100, '원거리 공격')
tank_1.show_status()

​print


이름: Tank
등급: 시즈탱크
사이즈: Big
라이프: 100
공격 타입: 원거리 공격

코드를 살펴보면, Unit이라는 공통된 속성을 만들고, Tank라는 새로운 유닛을 선언하고, 상속을 시켜줬다.

그러나 여기서 내가 Tank 클래스만의 고유한 속성을 주려고 할때 위와 같은 방식으로 새로운 메소드들을 추가한다면, 상속과 클래스를 상요하는 의미가 없어진다.

이러한 문제를 해결하기 위해서 우리는 Super()라는 메소드를 활용하여, 부모 속성에 접근하여 오버라이딩하는 방식으로 수정하려고 한다.

Clean Code


class Unit(object):
    def __init__(self, rank, size, life):
        # 상속받는 클래스의 이름을 가져온다
        self.name = self.__class__.__name__
        self.rank = rank
        self.size = size
        self.life = life

    def show_status(self):
        print(f'이름: {self.name}')
        print(f'등급: {self.rank}')
        print(f'사이즈: {self.size}')
        print(f'라이프: {self.life}')

class Tank(Unit):
    def __init__(self, rank, size, life, attack_type):
        super(Tank, self).__init__(rank, size, life)
        self.attack_type = attack_type

    def show_status(self):
        super().show_status()
        print(f'공격 타입 : {self.attack_type}')

super() 메소드를 활용하여 부모 속성에 접근하였고, 부모 속성중에서 필요한 인자들은 그래도 사용하고, 추가적으로 필요한 부분만 클래스 내부에 새로 선언해주었다.

Super 메소드 활용법


  • super(자신의 클래스명, self).<부모클래스에서 가져올 메소드 명>
  • super().<부모클래스에서 가져올 메소드 명>

Super 함수를 활용하여 이미 부모 클래스에서 정의된 메소드를 호출하여 같은 코드를 반복하지 않도록 한다.

여기서 한가지! 스타크래프트라는 게임에는 탱크가 변신을 하여 한층 강력해진 공격력을 갖게 된다. 시즈모드라고 하는데 이 기능도 추가해보려고한다. 일단 기본적으로 탱크의 속성을 갖고 있어야하므로 시즈모드라는 클래스를 만들고 탱크라는 속성을 상속시켜준다.

class Unit(object):
    def __init__(self, rank, size, life):
        # 상속받는 클래스의 이름을 가져온다
        self.name = self.__class__.__name__
        self.rank = rank
        self.size = size
        self.life = life

    def show_status(self):
        print(f'이름: {self.name}')
        print(f'등급: {self.rank}')
        print(f'사이즈: {self.size}')
        print(f'라이프: {self.life}')

class Tank(Unit):
    def __init__(self, rank, size, life, attack_type):
        super(Tank, self).__init__(rank, size, life)
        # self.attack_type = attack_type

    def show_status(self):
        super().show_status()
        # print(f'공격 타입 : {self.attack_type}')

class SiegeTank(Tank):
    def __init__(self, rank, size, life, attack_type, damage, SiegeTank_damage):
        super(SiegeTank, self).__init__(rank, size, life, attack_type, damage)
        self.SiegeTank_damage = SiegeTank_damage

    def show_status(self):
        super(SiegeTank, self).show_status()
        print('시즈모드 데미지: {}'.format(self.SiegeTank_damage))

이렇게 Tank 클래스를 상속 시키면 맨 마지만 SiegeTank 클래스는 Unit의 속성과 Tank의 속성을 둘 다 취할 수 있게 된다.

 

반응형
LIST