강의노트 10. [객체지향] 파이썬 추상클래스(abstract class), 다형성(polymorphism)

|

패스트캠퍼스 컴퓨터공학 입문 수업을 듣고 중요한 내용을 정리했습니다. 개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.

객체지향개발(OOP) 4가지 특성

객체지향개발(Object Oriented Programming)의 특성은 크게 추상화, 캡슐화, 상속성, 다형성이 있다.

  1. 추상화(Abstraciton)
    • 공통의 속성이나 기능을 묶어 이름을 붙이는 것
    • OOP 에서 클래스를 정의하는 것을 추상화라고 할 수 있다.
  2. 캡슐화 (Encapsulation)
    • 변수와 함수를 하나로 묶어서 외부에서의 접근을 막고, 함수를 통해서만 접근 가능하도록 하는 것
    • 객체가 맡은 역할을 수행하기 위한 데이터를 하나로 묶는다 (은닉화)
  3. 상속성, 재사용 (Inheritance)
    • 상위 개념의 특징을 하위 개념이 물려 받는 것
  4. 다형성 (Polymorphism)
    • 부모 클래스로부터 물려받은 가상 함수를 자식 클래스 내에서 오버라이딩 하여 사용하는 것

참고자료

추상화 클래스 (Abstract Base Class)

  • 게임에 존재하는 캐릭터는 hp, 공격력 등 공통적으로 갖고 있는 공통 특성이 있다.
  • 이러한 공통 특성을 가진 부모 클래스를 만들고 해당 클래스는 객체 인스턴스를 생성할 수 없게 하는것을 추상 클래스 (abstract class)라고 한다.
  • 추상 클래스 이해에 도움이 되는 글 : ‘다시 말해 추상클래스란 해당 클래스를 통해 만들어낸 객체가 전혀 객체의 모습을 띄지 못할 때, 해당 클래스가 객체를 생성할 수 없도록 하는 것. 너는 너무 추상적이야, 그래서 객체를 만들면 안돼!’

추상클래스(abstract class) 예시

  • 게임의 모든 캐릭터가 가진 공통 속성을 정의하는 Character 클래스를 정의한다. (단, 추상 클래스로 정의한다.)
  • 추상클래스는 @abstractmethod 데코레이터를 활용한 1개 이상의 abstract method를 가져야 한다.
  • 추상크래스를 정의 할 때는 from abc import * 모듈 적용이 필요하다.

Character 클래스 (추상클래스, 부모클래스)

# character.py
from abc import * # Abstrace Base Class

class Character(metaclass = ABCMeta):
  def __init__(self):
    self.hp = 100
    self.attack_power = 20

  def attack(self, other, attack_kind):
    other.get_damage(self.attack_power, attack_kind)

  @abstractmethod # Character 클래스를 상속받는 모든 클래스는 하기 함수를 오버라이딩으로 구현해야 인스턴스 생성이 가능하다.  
  def get_damage(self, attack_power, attack_kind):
    pass

# 테스트코드    
if __name__ == '__main__':
    ch1 = Character()  # TypeError 발생 (Can't instantiate abstract class Character with abstract methods get_damage)


다형성 (polymorphism)

  • 상속과 함께 OOP에서 중요한 개념 중 하나
  • 동일한 코드이지만 동작방법, 결과가 다른 것을 의미한다.
  • 다형성의 쉬운 예제는 Java의 오버로딩이다. 오버로딩은 같은 의미지만 매개변수의 데이터타입이 무엇이냐에 따라서 다른 메소드가 호출되는 방식이다. 참고 (참고로 파이썬은 오버로딩을 허용하지 않는다.)
  • 다형성을 잘 쓰면 IF / ELSE 문을 많이 줄일 수 있다.
  • 다형성에 대한 이해하기 쉬운 글

다형성 (polymorphism) 예시

  • 추상클래스인 Character 클래스를 상속 받아서 Player, Monster 클래스를 각각 정의한다.

추상클래스의 자식 클래스 (Player)

# player.py
from character import Character

class Player(Character):

  def get_damage(self, attack_power, attack_kind):
    self.hp -= attack_power

추상클래스의 자식 클래스 (IceMonster, FireMonster : 다형성 적용)

  • 매개변수 attack_kind에 따라서 get_damage 메소드의 작동 방식을 분기처리한다.
# monster.py
from character import Character

class IceMonster(Character):
  def get_damage(self, attack_power, attack_kind):
    if attack_kind == 'ICE':
      self.hp += attack_power
    else:
      self.hp -= attack_power

  def __str__(self):
        return "Ice Monster's HP : {}".format(self.hp)

class FireMonster(Character):
  def get_damage(self, attack_power, attack_kind):
    if attack_kind == 'FIRE':
      self.hp += attack_power
    else:
      self.hp -= attack_power

  def __str__(self):
    return "Fire Monster's HP : {}".format(self.hp)

실행 파일작성 (main.py)

# main.py

from player import Player
from monster import *

play = Player()
ice = IceMonster()
fire = FireMonster()

print(ice) # Ice MOnster's HP : 100
print(fire) # Fire MOnster's HP : 100

# 확인방법 1
play.attack(ice, 'ICE')
play.attack(fire, 'ICE')

print(ice) # Ice MOnster's HP : 120
print(fire) # Fire MOnster's HP : 80

# 확인방법 2
monsters = []
monsters.append(ice)
monsters.append(fire)

for monster in monsters:
  play.attack(monster, 'ICE')
  print(monster)

# Ice Monster's HP : 140
# Fire Monster's HP : 60