다중 상속을 지원하는 언어에선 별개의 상위클래스가 동일한 이름으로 메서드를 구현하 ㄹ때 발생하는 이름 충돌 문제(다이아몬드 문제)를 해결해야 한다.
"""
B클래스와 C클래스 모두 pong() 메서드를 구현하고 있지만, C.pong() 메서드는 대문자로 출력한다는 것이 다르다.
"""
class A:
def ping(self):
print('ping:', self)
class B(A):
def pong(self):
print("pong", self)
class C(A):
def pong(self):
print("pong", self)
class D(B,C):
def ping(self):
super().ping()
print("post-ping:", self)
def pingpong(self):
self.ping()
super().ping()
self.pong()
super().pong()
C.pong(self)
D클래스 객체의 pong() 메서드를 호출하는 두 가지 방법
from diamond import *
d = D()
d.pong()
C.pong(d)
파이썬이 상속 그래프를 조회할 때는 특정한 순서를 따르고, d.pong()과 같은 호출의 모호함이 해결되고, 이 순서를 메서드 결정 순서(MRO)라고 한다. 클래스에 있는 mro속성은 현재 클래스부터 object 클래스까지 슈퍼 클래스들의 MRO를 튜플 형태로 저장한다.
슈퍼클래스 메서드에 위힘할 때는 내장 함수인 super()를 사용하는 것이 좋다
def ping(self):
A.ping(self) # super().ping() 대신 호출
print('post-ping:', self)
객체 메서드를 클래스에 직접 호출할 때는 self를 반드시 명시해야 하고, 바인딩되지 않은 메서드에 접근하는 것이기 때문이다. 그러나, 프레임워크 혹은 여러분이 직접 제어할 수 없는 클래스 계층 구조에 들어 있는 메서드를 호출할 때는 super()를 사용하는 것이 안전하며, 향우 프레임워크가 변경 되어도 문제없이 작동한다.
from diamond import D
d = D()
d.ping()