whatisthis?
Phython. 파이썬 코딩 기초편-08(下) 본문
7. 메소드 오버라이딩
자식클래스에서 정의한 메소드를 사용하고 싶을 때, 메소드 오버라이딩을 사용.
1. Unit 클래스에 move 함수를 추가로 정의한다.
지상 유닛이 이동하는 경우의 move이다.
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))
그리고, 이전에 날 수 있는 클래스였던 flyable 클래스에서 정의한
fly 함수의 경우에는 다음과 같았다.
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))
만약, 지상 유닛의 경우라면 Unit 클래스의 move함수를 이용해야하고,
공중 유닛의 경우에는 Flyable 클래스의 fly함수를 이용해야 한다.
그러나, 이런 경우에는 함수 이름이 다르기때문에 해당 유닛이 공중유닛인지 지상유닛인지 일일히 확인해야하는
불편함이 존재한다.
이때 해결하는 방법이 바로 메소드 오버라이딩 이다.
def move(self, location):
print("[공중 유닛 이동]")
self.fly(self.name, location)
다음과 같이 FlyableAttackUnit 클래스에 move함수를 추가해준다.
fly 함수의 경우에는 이름도 입력받도록 (name) 되어있으나
move함수에서는 self.name을 이용할 수 있도록 해보았다.
따라서
vulture.move("11시")
battlecruiser.fly("battlecrusier.name, "9시")
와 같이 move와 fly를 구분하여 작성해야했던 코드를
vulture.move("11시")
battlecruiser.move("9시")
와 같이 입력할 수 있다.
** 단,
vulture = AttackUnit("벌쳐", 80, 10, 20) battlecruiser = FlyableAttackUnit("배틀크루저", 500, 25, 3) |
와 같이 이미 클래스로 선언된 객체이기 때문에 각자의 클래스에 맞춰 move함수를 실행한 것이다.
# 일반 유닛
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):
print("{0} : {1} 방향으로 적군을 공격합니다. [공격력 {2}]".format(self.name, location, self.damage))
# name과 attack은 self값을 사용했으나, attack은 전달받은 값을 사용한다는 의미이다.
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 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, 0, damage) # 지상 스피드는 0
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시")
8. pass
함수가 완성된것처럼 일단은 지나가라는 의미.
약간 continue 와 비슷한 개념.
그러나 이건 함수 내에 본문에 사용하는 것임.
예>
def game_start():
print("새로운 게임을 시작합니다.")
def game_over():
pass
game_start()
game_over()
9. Super
class BuildingUnit(Unit):
def __init__(self, name, hp, location):
Unit.__init__(self, name, hp, 0) # speed는 0이므로
self.location = location
원래는 상속을 할때
부모클래스명.__init__(self, 부모매소드들)과 같이 했는데,
super를 이용해서 할 수도 있다.
**참고 : Unit 클래스의 매소드 중에서 speed는 필요없으므로 0으로 적는다.
class BuildingUnit(Unit):
def __init__(self, name, hp, location):
super().__init__(name, hp, 0)
self.location = location
작성 방법은
super().__init__(부모매소드들) 과 같다.
대신, super()을 이용할 때에는 self 를 적지 않아도 된다.
Unit.__init__(self, name, hp, 0) |
super().__init__(name, hp, 0) |
+) 다중 상속을 할 때 문제점
class Unit:
def __init__(self):
print("Unit 생성자")
class Flyable:
def __init__(self):
print("Flyable 생성자")
class FlyableUnit(Unit, Flyable):
def __init__(self):
super().__init__()
#드랍쉽
dropship = FlyableUnit()
위와 같이 간단한 버전의 예제를 만들어보자.
만약 두개 이상의 부모 클래스에게 상속을 받는다면(=다중상속)
super()를 이용하면 맨 처음에 오는 부모클래스에만 init함수가 호출이 된다.
** 다중 상속시에는 super()로 하면 안되고,
원래의 방식대로 Unit.__init__(self, name, hp, 0) 와 같이 해줘야한다.
<Assignment> 스타크래프트 게임
Ch8에서 진행했던 스타크래프트 예제를 보고 살을 붙혀서
실제 스타크래프트처럼 (텍스트 기반) 플레이할 수 있도록 해보자!
1. 일반 유닛 = 공격은 못하지만 damaged함수(피해 받는것)는 가능하므로
기본 클래스인 unit 클래스에 damaged 함수를 붙여넣는다.
2. 각 유닛에 해당하는 클래스들을 만든다.
1) 마린
2) 탱크
3) 레이스 (=공중 유닛)
# 일반 유닛
class Unit:
def __init__(self, name, hp, speed):
self.name = name
self.hp = hp
self.speed = speed
print("{0} 유닛이 생성되었습니다.".format(name)) #self.name으로 써도 ok
def move(self, location):
print("[지상 유닛 이동]")
print("{0} : {1} 방향으로 이동합니다. [속도 {2}]".format(self.name, location, self.speed))
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 AttackUnit(Unit):
def __init__(self, name, hp, speed, damage):
Unit.__init__(self, name, hp, speed)
self.damage = damage
def attack(self, location):
print("{0} : {1} 방향으로 적군을 공격합니다. [공격력 {2}]".format(self.name, location, self.damage))
# name과 attack은 self값을 사용했으나, attack은 전달받은 값을 사용한다는 의미이다.
# 마린
class Marine(AttackUnit):
def __init__(self):
AttackUnit.__init__(self, "마린", 40, 1, 5)
# 스팀팩 = 체력 10을 써서 이동및 공격속도 증가
def stimpack(self):
if self.hp > 10:
self.hp -= 10
print("{0} : 스팀팩을 사용합니다. (HP 10감소)".format(self.name))
else:
print("{0} : 체력이 부족하여 스팀팩을 사용하지 못합니다.".format(self.name))
# 탱크
class Tank(AttackUnit):
# 시즈모드 = 탱크를 고정시켜 더 높은 공격력.
seize_developed = False
def __init__(self):
AttackUnit.__init__(self, "탱크", 150, 1, 35)
self.seize_mode = False
def set_seize_mode(self):
if Tank.seize_developed == False:
return
if self.seize_mode == False:
print("{0} : 시즈모드로 전환합니다.".format(self.name))
self.damage *= 2
self.seize_mode = True
else:
print("{0} : 시즈모드로 해제합니다.".format(self.name))
self.damage /= 2
self.seize_mode = False
# 날 수 있는 클래스
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, 0, damage) # 지상 스피드는 0
Flyable.__init__(self, flying_speed)
def move(self, location):
print("[공중 유닛 이동]")
self.fly(self.name, location)
# 레이스
class Wraith(FlyableAttackUnit):
def __init__(self):
FlyableAttackUnit.__init__(self, "레이스", 80, 20, 5)
self.clocked = False # 클로킹 모드
def clocking(self):
if self.clocked == False:
print("{0} : 클로킹 모드로 전환합니다.".format(self.name))
self.clocked == True
else:
print("{0} : 클로킹 모드를 해제합니다.".format(self.name))
self.clocked == False
3. 실제 게임 플레이를 시뮬레이션
def game_start():
print("[알림] 새로운 게임을 시작합니다.")
def game_over():
print("Player : gg")
print("[player] 님이 게임에서 퇴장하셨습니다.")
# 실제 게임 진행
game_start()
# 유닛 생성
m1 = Marine()
m2 = Marine()
m3 = Marine()
t1 = Tank()
t2 = Tank()
w1 = Wraith()
# 유닛 일괄 관리 (생성된 모든 유닛 append)
attack_units = []
attack_units.append(m1)
attack_units.append(m2)
attack_units.append(m3)
attack_units.append(t1)
attack_units.append(t2)
attack_units.append(w1)
# 전군 이동
for unit in attack_units:
unit.move("1시")
# 탱크 시즈모드 개발
Tank.seize_developed = True
print("[알림] 탱크 시즈 모드 개발이 완료되었습니다.")
# 공격 모드 준비 (스팀팩, 시즈모드, 클로킹)
for unit in attack_units:
if isinstance(unit, Marine):
unit.stimpack()
elif isinstance(unit, Tank):
unit.set_seize_mode()
elif isinstance(unit, Wraith):
unit.clocking()
# 전군 공격
for unit in attack_units:
unit.attackk("1시")
# 피해 입음
for unit in attack_units:
unit.damaged(randint(5,20)) # 공격은 랜덤으로 받음
# 우리 유닛 다 죽음 - 게임종료
game_over()
<최종 실행 결과>
[알림] 새로운 게임을 시작합니다.
마린 유닛이 생성되었습니다.
마린 유닛이 생성되었습니다.
마린 유닛이 생성되었습니다.
탱크 유닛이 생성되었습니다.
탱크 유닛이 생성되었습니다.
레이스 유닛이 생성되었습니다.
[지상 유닛 이동]
마린 : 1시 방향으로 이동합니다. [속도 1]
[지상 유닛 이동]
마린 : 1시 방향으로 이동합니다. [속도 1]
[지상 유닛 이동]
마린 : 1시 방향으로 이동합니다. [속도 1]
[지상 유닛 이동]
탱크 : 1시 방향으로 이동합니다. [속도 1]
[지상 유닛 이동]
탱크 : 1시 방향으로 이동합니다. [속도 1]
[공중 유닛 이동]
레이스 : 1시 방향으로 날아갑니다. [속도 5]
[알림] 탱크 시즈 모드 개발이 완료되었습니다.
마린 : 스팀팩을 사용합니다. (HP 10감소)
마린 : 스팀팩을 사용합니다. (HP 10감소)
마린 : 스팀팩을 사용합니다. (HP 10감소)
탱크 : 시즈모드로 전환합니다.
탱크 : 시즈모드로 전환합니다.
레이스 : 클로킹 모드로 전환합니다.
마린 : 1시 방향으로 적군을 공격합니다. [공격력 5]
마린 : 1시 방향으로 적군을 공격합니다. [공격력 5]
마린 : 1시 방향으로 적군을 공격합니다. [공격력 5]
탱크 : 1시 방향으로 적군을 공격합니다. [공격력 70]
탱크 : 1시 방향으로 적군을 공격합니다. [공격력 70]
레이스 : 1시 방향으로 적군을 공격합니다. [공격력 20]
마린 : 20 데미지를 입었습니다.
마린 : 현재 체력은 10입니다.
마린 : 15 데미지를 입었습니다.
마린 : 현재 체력은 15입니다.
마린 : 15 데미지를 입었습니다.
마린 : 현재 체력은 15입니다.
탱크 : 20 데미지를 입었습니다.
탱크 : 현재 체력은 130입니다.
탱크 : 14 데미지를 입었습니다.
탱크 : 현재 체력은 136입니다.
레이스 : 19 데미지를 입었습니다.
레이스 : 현재 체력은 61입니다.
Player : gg
[player] 님이 게임에서 퇴장하셨습니다.
<Quiz>
주어진 코드로 부동산 프로그램을 작성하시오.
출력 예시.
총 3대의 매물이 있습니다. 강남 아파트 매매 10억 2010년 마포 오피스텔 전세 5억 2007년 송파 빌라 월세 500/50 2000년 |
[코드]
class House:
# 매물 초기화
def __init__(self, location, house_type, deal_type, price, year):
pass
# 매물 정보 표시
def show_detail(self):
pass
'WEB STUDY > PHYTHON | BACK-END' 카테고리의 다른 글
Phython. 파이썬 코딩 기초편-10(上) (0) | 2021.09.20 |
---|---|
Phython. 파이썬 코딩 기초편-09 (2) | 2021.09.20 |
Phython. 파이썬 코딩 기초편-08(上) (0) | 2021.09.18 |
Phython. 파이썬 코딩 기초편-07 (3) | 2021.09.16 |
Phython. 파이썬 코딩 기초편-06 (4) | 2021.09.15 |