TIL_28 : 상속
🙄 상속
➡ 상속이란?
- 두 클래스 사이에 부모-자식 관계를 설정하는 것
- 자식 클래스는 부모 클래스의 모든 변수와 메소드를 상속 받음
➡ 부모 클래스 정의하기
- 아래 두 클래스는 유사한 부분이 많은 계산대 직원 클래스, 배달 직원 클래스
- 부모 클래스
Employee
를 만들어보자
class Cashier:
"""계산대 직원 클래스"""
company_name = "버거버거"
raise_percentage = 1.03
burger_price = 4000
def __init__(self, name, wage, number_sold=0):
self.name = name
self.wage = wage
self.number_sold = number_sold
def raise_pay(self):
"""시급을 인상한다"""
self.wage *= self.raise_percentage
def take_order(self, money_received):
"""주문과 돈을 받고 거스름돈을 리턴한다"""
if Cashier.burger_price > money_received:
print("돈이 충분하지 않습니다.")
return money_received
else:
self.number_sold += 1
change = money_received - Cashier.burger_price
return change
def __str__(self):
return Cashier.company_name + " 계산대 직원: " + self.name
class DeliveryMan:
"""배달원 클래스"""
company_name = "버거버거"
raise_percentage = 1.03
def __init__(self, name, wage, on_standby):
self.name = name
self.wage = wage
self.on_standby = on_standby
def raise_pay(self):
"""시급을 인상한다"""
self.wage *= self.raise_percentage
def deliver(self, address):
"""배달원이 대기 중이면 주어진 주소로 배달을 보내고 아니면 설명 메시지를 출력한다"""
if self.on_standby:
print(address + "로 배달 나갑니다!")
self.on_standby = False
else:
print("이미 배달하러 나갔습니다!")
def back(self):
"""배달원을 복귀 처리한다"""
self.on_standby = True
def __str__(self):
return DeliveryMan.company_name + " 배달원: " + self.name
- 중복되는 부분을 부모 클래스에 써주고 자식 클래스에서 지우면 됨
class Employee:
"""직원 클래스"""
company_name = "버거버거"
raise_percentage = 1.03
def __init__(self, name, wage):
self.name = name
self.wage = wage
def raise_pay(self):
"""시급을 인상한다"""
self.wage *= self.raise_percentage
def __str__(self):
return Employee.company_name + " 직원: " + self.name
class Cashier:
burger_price = 4000
def __init__(self, name, wage, number_sold=0):
self.number_sold = number_sold
def take_order(self, money_received):
"""주문과 돈을 받고 거스름돈을 리턴한다"""
if Cashier.burger_price > money_received:
print("돈이 충분하지 않습니다.")
return money_received
else:
self.number_sold += 1
change = money_received - Cashier.burger_price
return change
class DeliveryMan:
def __init__(self, name, wage, on_standby):
self.on_standby = on_standby
def deliver(self, address):
"""배달원이 대기 중이면 주어진 주소로 배달을 보내고 아니면 설명 메시지를 출력한다"""
if self.on_standby:
print(address + "로 배달 나갑니다!")
self.on_standby = False
else:
print("이미 배달하러 나갔습니다!")
def back(self):
"""배달원을 복귀 처리한다"""
self.on_standby = True
👉 지금까지는 서로 다른 클래스 3개일뿐 상속관계가 아님
👉class 자식 클래스(부모 클래스):
로 상속관계 설정
상속관계 설정하기
class Employee:
"""직원 클래스"""
company_name = "버거버거"
raise_percentage = 1.03
def __init__(self, name, wage):
self.name = name
self.wage = wage
def raise_pay(self):
"""시급을 인상한다"""
self.wage *= self.raise_percentage
def __str__(self):
return Employee.company_name + " 직원: " + self.name
class Cashier(Employee):
pass
goldstlme = Cashier("민정호", 8900)
goldstlme.raise_pay()
print(goldstlme.wage)
print(goldstlme)
# 9167.0
# 버거버거 직원: 민정호
👉
Cashier
는 비어있지만 부모 클래스의 인스턴스, 메소드 정상 작동
➡ 상속과 관련된 메소드 & 함수
.mro()
: 인스턴스의 클래스가 어떤 부모 클래스를 가지는지 보여준다.isinstance()
: 특정 클래스의 인스턴스가 맞는지 판별
1. 첫 번째 파라미터에는 검사할 인스턴스의 이름
2. 두 번째 파라미터에는 기준 클래스의 이름issubclass()
: 한 클래스가 다른 클래스의 자식 클래스인지 판별
1. 첫 번째 파라미터로 검사할 클래스의 이름
2. 두 번째 파라미터에는 기준이 되는 부모 클래스의 이름
class Employee:
"""직원 클래스"""
company_name = "버거버거"
raise_percentage = 1.03
def __init__(self, name, wage):
self.name = name
self.wage = wage
def raise_pay(self):
"""시급을 인상한다"""
self.wage *= self.raise_percentage
def __str__(self):
return Employee.company_name + " 직원: " + self.name
class Cashier(Employee):
pass
class DeliveryMan(Employee):
pass
goldstlme = Cashier("민정호", 8900)
print(Cashier.mro())
# [<class '__main__.Cashier'>, <class '__main__.Employee'>, <class 'object'>]
print(isinstance(goldstlme, Cashier)) # True
print(isinstance(goldstlme, DeliveryMan)) # False
print(isinstance(goldstlme, Employee)) # True
# 자식 클래스로 만든 인스턴스는 부모 클래스의 인스턴스이기도 하다!!
print(issubclass(Cashier, Employee)) # True
➡ 오버라이딩
- 오버라이딩 : 덮어쓰기, 부모로부터 물려받은 것을 자신에 맞게 수정
- 물려받기만 해서는 자식 클래스를 제대로 사용할 수 없다
- 물려받기만 하면 자식클래스들간의 차이가 없기 때문
class Employee:
"""직원 클래스"""
company_name = "버거버거"
raise_percentage = 1.03
def __init__(self, name, wage):
"""인스턴스 변수 설정"""
self.name = name
self.wage = wage
def raise_pay(self):
"""시급을 인상한다"""
self.wage *= self.raise_percentage
def __str__(self):
"""직원 정보를 문자열로 리턴하는 메소드"""
return Employee.company_name + " 직원: " + self.name
class Cashier(Employee):
# 변수 오버라이딩
raise_percentage = 1.05
# 메소드 오버라이딩
def __init__(self, name, wage, number_sold):
# super 함수로 부모 클래스의 메소드를 사용할 땐 self 파라미터가 필요 없다
Employee.__init__(self, name, wage)
super().__init__(name, wage)
self.number_sold = number_sold
def __str__(self):
return Cashier.company_name + " 계산대 직원: " + self.name
goldstlme = Cashier("민정호", 8000, 4)
print(goldstlme) # 버거버거 계산대 직원: 민정호
print(goldstlme.name) # 민정호
print(goldstlme.wage) # 8000
print(goldstlme.number_sold) # 4
print(Cashier.raise_percentage) # 1.05
➡ 다중상속
- 다중 상속 시, 여러 부모 클래스에 같은 이름의 메소드가 있다면 상속 파라미터 순서에 따라 다른 값이 출력되는 위험성이 있음
👉 이를 방지하기 위해 부모 클래스끼리 같은 이름의 메소드를 갖지 않도록 하고
👉 같은 이름의 메소드는 자식 클래스에서 오버라이딩함으로써 해결
# 엔지니어 클래스
class Engineer:
def __init__(self, favorite_language):
self.favorite_language = favorite_language
def program(self):
print("{}(으)로 프로그래밍합니다.".format(self.favorite_language))
# 테니스 선수 클래스
class TennisPlayer:
def __init__(self, tennis_level):
self.tennis_level = tennis_level
def play_tennis(self):
print("{} 반에서 테니스를 칩니다".format(self.tennis_level))
# 다중상속된 자식 클래스
class EngineerTennisPlayer(Engineer, TennisPlayer):
def __init__(self, favorite_language, tennis_level):
# super()를 이용하면 어느 부모 클래스를 오버라이딩하는지 알 수 없음
Engineer.__init__(self, favorite_language) # 오버라이딩
TennisPlayer.__init__(self, tennis_level) # 오버라이딩
# 다중 상속을 받는 클래스의 인스턴스 생성
jahyeon = EngineerTennisPlayer("파이썬", "초급")
# 두 부모 클래스의 메소드들을 잘 물려받았는지 확인
jahyeon.program() # 파이썬(으)로 프로그래밍합니다.
jahyeon.play_tennis() # 초급 반에서 테니스를 칩니다
Author And Source
이 문제에 관하여(TIL_28 : 상속), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@wumusill/TIL29-상속-다형성저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)