10.1 Dziedziczenie z kilku klas
Dziedziczenie wielokrotne w Pythonie pozwala klasie dziedziczyć atrybuty i metody z więcej niż jednej klasy bazowej. To daje większą elastyczność i pozwala na ponowne użycie kodu, ale może również prowadzić do skomplikowanych hierarchii i potencjalnych konfliktów.
Możliwość wymienienia pięciu rodziców dla swojej klasy znacznie rozszerza twoje możliwości i ułatwia pisanie kodu. Jest to bardzo proste — wystarczy wymienić klasy-rodzice oddzielone przecinkiem:
class Base1:
def method1(self):
print("Method1 from Base1")
class Base2:
def method2(self):
print("Method2 from Base2")
class Derived(Base1, Base2):
pass
obj = Derived()
obj.method1()
obj.method2()
Wszystko działa zgodnie z planem — pięknie.
Jednak dziedziczenie wielokrotne ma kilka złożonych aspektów, które musisz wziąć pod uwagę przy jego używaniu. Przyjrzyjmy się, jak to działa i jak unikać problemów związanych z dziedziczeniem wielokrotnym.
10.2 Wywołanie metody, która istnieje w kilku klasach bazowych
Klasa może dziedziczyć atrybuty i metody z kilku klas bazowych, wymienionych w nawiasach po nazwie klasy. I te atrybuty i metody mogą mieć takie same nazwy:
class Base1:
def method(self):
print("Method from Base1")
class Base2:
def method(self):
print("Method from Base2")
class Derived(Base1, Base2):
pass
obj = Derived()
obj.method() # która metoda zostanie wywołana?
W tym przykładzie klasa Derived
dziedziczy z Base1
i Base2
. Kiedy wywoływana jest method()
, Python wybierze metodę pierwszej wymienionej klasy — Base1
.
Ale to nie jest takie oczywiste, prawda? I jeśli ktoś zmieni kod klasy bazowej, może ucierpieć cała logika aplikacji, a ty nawet nie będziesz wiedzieć, że coś jest nie tak. Po prostu zaczną być wywoływane nieco inne metody :)
10.3 Użycie super()
z dziedziczeniem wielokrotnym
Kolejną ciekawą cechą jest wywołanie super()
dla klasy bazowej przy dziedziczeniu wielokrotnym.
Przykład:
class Base1:
def method(self):
print("Method from Base1")
super().method()
class Base2:
def method(self):
print("Method from Base2")
super().method()
class Derived(Base1, Base2):
def method(self):
print("Method from Derived")
super().method()
obj = Derived()
obj.method()
No i co? Jaki będzie wynik na ekranie?
Method from Derived
Method from Base1
Albo
Method from Derived
Method from Base2
Mam dla ciebie niespodziankę — wynik będzie taki:
Method from Derived
Method from Base1
Method from Base2
Kod super().method()
wywoła metodę method()
u każdej klasy bazowej! To są właśnie te niuanse, o których wspominałem przy pierwszym wspomnieniu o dziedziczeniu wielokrotnym.
10.4 Diamentowe (Diamond)
dziedziczenie
I wreszcie, klasyczny problem diamentowego dziedziczenia. Łatwiej to pokazać na przykładzie, niż opisywać:

W postaci kodu może to wyglądać na przykład tak:
class A:
def method(self):
print("Method from A")
class B(A):
def method(self):
print("Method from B")
super().method()
class C(A):
def method(self):
print("Method from C")
super().method()
class D(B, C):
def method(self):
print("Method from D")
super().method()
obj = D()
obj.method()
Wynik będzie taki:
Method from D
Method from B
Method from C
Method from A
Aby móc orientować się w dziedziczeniu wielokrotnym, musisz dobrze wiedzieć, w jakiej kolejności Python szuka pól i metod w klasach bazowych. Właśnie o tym dowiesz się na kolejnej lekcji.
GO TO FULL VERSION