부모 클래스를 상속 받는 자식 클래스가 있을 경우 super
내장 함수를 이용해 다이아몬드 계층의 공통 상위 클래스를 단 한 번만 호출하도록 할 수 있다.
다이아몬드 계층이란?
아래의 코드를 이용하면 다이아몬드 모양의 클래스 구조를 다시 만드는 대신 super
를 사용해 부모 클래스를 초기화 한다.
그러면 다이아몬드의 정점에 있는 MyBaseClass
에 도달했을 때 MyBaseClass.__init__
이 한 번만 호출 되어 중간에 오버라이딩 되면서 생기는 문제가 사라진다.
오버라이딩 되며 생기는 문제
(예시) 아래의 예시는 파이썬 코딩의 기술(개정 2판, 브렛 슬라킨 저)에서 가져온 것입니다.
# 부모 클래스
class MyBaseClass:
def __init__(self, value):
self.value = value
# 자식 클래스
class TimesSeven(MyBaseClass):
def __init__(self, value):
MyBaseClass.__init__(self, value)
self.value *= 7
# 자식 클래스
class PlusNine(MyBaseClass):
def __init__(self, value):
MyBaseClass.__init__(self, value)
self.value += 9
아래와 같이, TimesSeven과 PlusNine을 모두 상속하는 자식 클래스를 정의하면 MyBaseClass가 다이아몬드 계층의 가장 상위에 있게 된다.
이 경우, 두 번째 부모 클래스의 생성자인 PlusNine.__init__(self, value)
를 호출할 때 MyBaseClass.init(self, value)가 다시 호출되면서 self.value가 5로 돌아간다.
이는 예상한 결과가 아니기 때문에 버그를 잡기 힘들 수 있다.
class ThisWay(TimesSeven, PlusNine):
def __init__(self, value):
TimesSeven.__init__(self, value)
PlusNine.__init__(self, value)
print(ThisWay(5).value) # (5 * 7) + 9 = 44가 아닌 14가 나옴
따라서, 아래와 같이 super
를 사용해서 다이아몬드 계층의 공통 상위 클래스를 한 번만 호출하도록 보장할 수 있다.
class TimesSeven(MyBaseClass):
def __init__(self, value):
super().__init__(self, value)
self.value *= 7
class PlusNine(MyBaseClass):
def __init__(self, value):
super().__init__(self, value)
self.value += 9
# TimesSeven과 PlusNine을 상속 받은 클래스
class GoodWay(TimesSeven, PlusNine):
def __init__(self, value):
super().__init__(self, value)
이제 MyBaseClass.__init__
이 한 번만 호출되어 오버라이딩으로 인한 문제점은 발생하지 않는다.
조금 더 분석해 보면,
__init__
이 호출된 순서의 역순으로 작업한다(호출은 역순으로 일어난다).