10.1 Ereditarietà da più classi
Ereditarietà multipla in Python permette a una classe di ereditare attributi e metodi da più di una classe genitore. Questo offre maggiore flessibilità e permette di riutilizzare il codice, ma può anche portare a gerarchie complesse e potenziali conflitti.
La possibilità di elencare alla tua classe cinque genitori amplia considerevolmente le tue possibilità e rende la scrittura del codice molto conveniente. Farlo è molto semplice — basta elencare le classi genitore separandole con una virgola:
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()
Tutto funziona come previsto — fantastico.
Tuttavia, l'ereditarietà multipla ha alcuni aspetti complessi che devi considerare quando la usi. Vediamo come funziona e come evitare i problemi legati all'ereditarietà multipla.
10.2 Chiamata di un metodo presente in più classi base
Una classe può ereditare attributi e metodi da più classi genitore, elencate tra parentesi dopo il nome della classe. E questi attributi e metodi possono avere nomi uguali:
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() # quale metodo verrà chiamato?
In questo esempio, la classe Derived
eredita da
Base1
e Base2
. Quando viene chiamato
method()
, Python sceglierà il metodo dalla prima classe
indicata — Base1
.
Ma non è così ovvio, vero? E se qualcuno modifica il codice della classe base, tutta la logica dell'applicazione potrebbe risentirne, e nemmeno saprai che qualcosa non va. Inizieranno semplicemente a chiamarsi metodi leggermente diversi :)
10.3 Uso di super()
con ereditarietà multipla
Un'altra caratteristica interessante è la chiamata a super()
per la classe base durante l'ereditarietà multipla.
Esempio:
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()
Allora? Quale sarà l'output?
Method from Derived
Method from Base1
Oppure
Method from Derived
Method from Base2
Ho una sorpresa per te — l'output sarà:
Method from Derived
Method from Base1
Method from Base2
Il codice super().method()
chiamerà il metodo
method()
di ciascuna classe base! Questo è proprio uno di quei
dettagli di cui parlavo la prima volta che ho menzionato l'ereditarietà
multipla.
10.4 Ereditarietà a rombo (Diamond)
E infine, il classico problema dell'ereditarietà a rombo. È più facile da mostrare con un esempio che da descrivere:
In codice può sembrare così, ad esempio:
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()
L'output sarà:
Method from D
Method from B
Method from C
Method from A
Per orientarti almeno un po' nell'ereditarietà multipla, devi sapere bene in quale ordine Python cerca i campi e i metodi delle classi genitore. Questo è proprio ciò che scoprirai nella prossima lezione.
GO TO FULL VERSION