Python

PyCharm - 상속, 추상 클래스

jomericano 2022. 5. 23. 19:33
# 상속
# 부모 클래스로부터 변수, 함수를 물려받아
# 새로운 클래스를 만드는 기법
# 한번 정의된 데이터유형을 필요에 따라
# 다시 재활용, 반복코드를 줄일 수있음

# 상속의 장점 : 중복코드 배베, 유지보수 용이
# 통일성 유지, 다형성 구현 용이

# 부모/ 상위 / 슈퍼

# calseee 자식클래스명(부모클래스명)
#          클래스 몸체




# 스타크래프트 유닛을 상속개념을 이용해서 구현

# 테란 진형 유닛을 클래스로 작성
# 해병대, 의무관, 화염방사병
# 각 클래스는 이름,생명력100,에너지100,공격력 멤버로 구성
# 모든 클래스는 기본적으로 이동능력을 가지고 있음
# 또한, 각 클래스 별 고유 능력을 하나씩 가지고 있음


class Marine:
    def __init__(self):
        self.name = self.__class__.__name__
        self.life = 100
        self.energy = 100
        self.power = 10

    def __str__(self):
        msg = f'{self.name}{self.life}{self.energy}{self.power}'
        return msg

    def move(self):
        print('지정한 위치로 이동하였습니다.')

    def attack(self):
        print(f'{self.power}플라즈마소총 공격중')

class Medic:
    def __init__(self):
        self.name = self.__class__.__name__
        self.life = 100
        self.energy = 100
        self.power = 1

    def __str__(self):
        msg = f'{self.name}{self.life}{self.energy}{self.power}'
        return msg

    def move(self):
        print('지정한 위치로 이동하였습니다.')

    def heal(self):
        print('지정한 유닛 치료중...')


class Firebat:
    def __init__(self):
        self.name = self.__class__.__name__
        self.life = 100
        self.energy = 100
        self.power = 10

    def __str__(self):
        msg = f'{self.name}{self.life}{self.energy}{self.power}'
        return msg

    def move(self):
        print('지정한 위치로 이동하였습니다.')

    def attack(self):
        print(f'공격중 {self.power} 화염방사')


# 테스트
marine = Marine()
print(marine)
marine.attack()
marine.move()

medic = Medic()
print(medic)
medic.heal()
medic.move()

firebat = Firebat()
print(firebat)
firebat.attack()
firebat.move()
# 상속을 이용하지 않고 유닛을 정의하는 경우
# 기능추가/ 수정시 관련있는 나머지 클래스에도 영향을 미침









class Terran:
        def __init__(self):            # power속성 따로정의
            self.name = self.__class__.__name__
            self.life = 100
            self.energy = 100

        def __str__(self):        # power속성 따로정의
            msg = f'{self.name},{self.life},{self.energy},'
            return msg

        def move(self):
            print('지정한 위치로 이동하였습니다.')

        def attack(self):
            # 유닛마다 공격유형 다르므로 정의 생략
            pass


class Marine(Terran):
    def __init__(self):
        # 부모클래스에 정의된 생성자를 호출하기 위해
        # super() 함수 사용   : overriding (재정의)
        super().__init__()
        self.power = 10

    def __str__(self):
        msg = super().__str__()
        msg += f'{self.power}'
        return msg


    def attack(self):
        print(f'공격력 {self.power} 플라즈마 소총으로 공격중...')




class Medic(Terran):
    def __init__(self):
        super().__init__()
        self.power = 10

    def __str__(self):
        msg = super().__str__()
        msg += f'{self.power}'
        return msg

    def attack(self):
        print(f'대상을 {self.power} 회복중...')





class Firebat(Terran):
    def __init__(self):
        super().__init__()
        self.power = 10

    def __str__(self):
        msg = super().__str__()
        msg += f'{self.power}'
        return msg

    def attack(self):
        print(f'공격력 {self.power} 화염방사 공격중...')


marine=Marine()
print(marine)
marine.move()
marine.attack()

medic=Medic()
print(medic)
medic.move()
medic.attack()
medic.attack()

firebat=Firebat()
print(firebat)
firebat.move()
firebat.attack()






# 게임캐릭터는 다음과 같이 3명 존재
# Warrior
# name: 클래스명, health = 100, attack = 10, defensive = 5

# Elf
# name: 클래스명, health = 100, attack = 10, defensive = 5

# Wizard
# name: 클래스명, health = 100, attack = 10, defensive = 5

# # Warrior
# -attack : 상대방 객체 입력바다 칼로찌르고 상대방 receive
# -receive : 상대방 attack 입력으로 받아서, 자신의 health를 낮춤

class diablo:
        def __init__(self):
            self.name = self.__class__.__name__
            self.health = 100

        def __str__(self):
            msg = f'{self.name},{self.health}'
            return msg

        def attack(self):
            print('')

        def receive(self):
            print(f'{self.health}-{self.attack()}')


class Warrior(diablo):
    def __init__(self):
        super().__init__()
        self.power = 10
        self.defensive =5

    def __str__(self):
        msg = super().__str__()
        msg += f'{self.power}'
        return msg

    def attack(self):
        print(f'공격력 {self.power}으로 공격중...')
    def receive(self):
        print(f'{self.health - self.power}')

class Elf(diablo):
    def __init__(self):
        super().__init__()
        self.power = 5
        self.defensive = 5

    def __str__(self):
        msg = super().__str__()
        msg += f'{self.power}'
        return msg

    def attack(self):
        print(f'대상을 {self.power} 공격중...')
    def receive(self):
        print(f'{self.health- self.power}')


class Wizard(diablo):
    def __init__(self):
        super().__init__()
        self.power = 3
        self.defensive = 3

    def __str__(self):
        msg = super().__str__()
        msg += f'{self.power}'
        return msg

    def attack(self):
        print(f'공격력 {self.power} 마법공격중...')
    def receive(self):
        print(f'{self.health - self.power}')

warrior = Warrior()
print(warrior)
warrior.attack()
warrior.receive()

elf = Elf()
print(elf)
elf.attack()
elf.receive()

wizard = Wizard()
print(wizard)
wizard.attack()
wizard.receive()

# 추상클래스

# 추상 메서드를 포함하는 클래스
# 추상 메서드 : 구현내용이 없는 메서드
# 추상 클래스(불완전한)는 객체화 불가!

# 추상 클래스를 상속받는 하위 클래스가
# 추상메서드를 반드시 구현하도록 강제하기 위해 사용

from abc import ABCMeta, abstractmethod


class Character(metaclass=ABCMeta):   # 추상클래스 정의
    def __init__(self):
        pass
    def __str__(self):
        pass
    @abstractmethod   # 추상메서드 정의
    def attacks(self):
        pass

    @abstractmethod
    def receives(self):
        pass


# 추상클래스 객체화 시도
c = Character()

# 추상클래스 상속해서 wizard 클래스 생성
class Wizard(Character):
    def attacks(self):
        pass

    def receives(self):
        pass


# Wizard 클래스 객체화
w= Wizard()