강의노트 10. [객체지향] 파이썬 추상클래스(abstract class), 다형성(polymorphism)
10 Apr 2017 |패스트캠퍼스 컴퓨터공학 입문 수업을 듣고 중요한 내용을 정리했습니다. 개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.
객체지향개발(OOP) 4가지 특성
객체지향개발(Object Oriented Programming)의 특성은 크게 추상화, 캡슐화, 상속성, 다형성이 있다.
- 추상화(Abstraciton)
- 공통의 속성이나 기능을 묶어 이름을 붙이는 것
- OOP 에서 클래스를 정의하는 것을 추상화라고 할 수 있다.
- 캡슐화 (Encapsulation)
- 변수와 함수를 하나로 묶어서 외부에서의 접근을 막고, 함수를 통해서만 접근 가능하도록 하는 것
- 객체가 맡은 역할을 수행하기 위한 데이터를 하나로 묶는다 (은닉화)
- 상속성, 재사용 (Inheritance)
- 상위 개념의 특징을 하위 개념이 물려 받는 것
- 다형성 (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