자식 클래스가 부모 클래스로부터 상속받은 메소드를 재정의(override)하는 것을 의미한다.
이 때 자식 클래스는 상속받은 메소드와 동일한 이름, 매개변수를 가지지만, 구체적인 실행 내용은 변경할 수 있다.
super
키워드: 자식 클래스에서는 super
키워드를 사용해서 부모 클래스의 메소드를 호출할 수 있다.부모 클래스로부터 상속을 받을 때 인스턴스화가 되는 시점에 부모로부터 상속을 받는다.
class ParentEx1():
def __init__(self):
self.value = 5
def get_value(self):
return self.value
class ChildEx1(ParentEx1):
pass
c1 = ChildEx1()
p1 = ParentEx1()
# 부모 & 자식 모든 속성 출력
print('Ex1 > ', dir(ParentEx1))
print('Ex1 > ', dir(ChildEx1))
"""
Ex1 > ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'get_value', 'value']
Ex1 > ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'get_value']
"""
# 부모 & 자식 인스턴스 속성 출력
print('Ex1 > ', ParentEx1.__dict__)
print('Ex1 > ', ChildEx1.__dict__)
"""
Ex1 > {'__module__': '__main__', '__init__': <function ParentEx1.__init__ at 0x0000028A15F81840>, 'get_value': <function ParentEx1.get_value at 0x0000028A15F818C8>, '__dict__': <attribute '__dict__' of 'ParentEx1' objects>, '__weakref__': <attribute '__weakref__' of 'ParentEx1' objects>, '__doc__': None}
Ex1 > {'__module__': '__main__', '__doc__': None}
"""
value
가 없다. value
는 부모 클래스의 __init__
메소드가 실행되면 생성되는 것이므로 메소드만 물려받은 자식 클래스에는 없는 것이 당연하다.class ParentEx2():
def __init__(self):
self.value = 5
def get_value(self):
return self.value
class ChildEx2(ParentEx1):
def get_value(self):
return self.value * 10
c2 = ChildEx2()
print('Ex2 > ', c2.get_value()) # 50
위와 같은 방식으로 부모클래스의 메소드를 재정의하여 같은 메소드로 다른 동작방식을 정의할 수 있다.
단! 위에 적었던 오버라이딩의 특징을 유념한 채 재정의 해야한다!
다형성에 대해 보기에 앞서 super()
함수에 대해 알아야 한다.
super()
자식클래스에서 부모 클래스를 호출할 때 사용된다.
super(자식클래스, 자식클래스의 인스턴스)
형태로 사용한다.super(Child, self).__init__()
:__init__
메소드를 호출super().__init__
:__init__
메소드를 호출import datetime
class Logger(object): # 로그메세지를 출력하는 부모클래스
def log(self, msg):
print(msg)
class TimestampLogger(Logger): # 로그메세지와 시간까지 출력하는 자식클래스
def log(self, msg):
message = "{ts} {msg}".format(ts=datetime.datetime.now(),
msg=msg)
# super().log(message)
super(TimestampLogger, self).log(message)
class DateLogger(Logger): # 더 정확한 시간표시를 해주는 자식클래스
def log(self, msg):
message = "{ts} {msg}".format(ts=datetime.datetime.now().strftime('%Y-%m-%d'),
msg=msg)
# super().log(message)
super(DateLogger, self).log(message)
l = Logger()
t = TimestampLogger()
d = DateLogger()
l.log("Called logger.")
t.log("Called timestamp logger.")
d.log("Called date logger.")
"""
Called logger.
2024-01-21 10:16:52.064729 Called timestamp logger.
2024-01-21 Called date logger.
"""