7.1 Metodo super()
Dal momento che abbiamo toccato la gerarchia di ereditarietà, è utile parlare di alcuni dettagli relativi al lavoro con i campi e i metodi della classe base. In Python, c'è un
metodo specifico super()
. Questo metodo è usato per richiamare i metodi di una classe base all'interno di una classe derivata.
Ha tre aree di utilizzo principali:
Richiamare metodi della classe genitore:
Il metodo super()
permette di richiamare un metodo della classe genitore da una classe derivata, senza specificare esplicitamente il nome della classe genitore. Questo è particolarmente utile quando si lavora con ereditarietà multipla e aiuta ad evitare errori quando si modifica la gerarchia delle classi.
Inizializzazione delle classi base:
super()
è spesso usato nel costruttore della classe derivata per richiamare il costruttore della classe base, consentendo di inizializzare gli attributi della classe base nella classe derivata.
Supporto per ereditarietà multipla:
In caso di ereditarietà multipla, super()
risolve correttamente l'ordine delle chiamate ai metodi (MRO, Method Resolution Order), il che rende il suo utilizzo preferibile rispetto alla chiamata esplicita dei metodi delle classi genitori. Di questo parleremo un po' più avanti.
7.2 Costruttore della classe base
Il costruttore della classe base deve essere richiamato esplicitamente. Sembra che avvenga automaticamente, ma in realtà non è così. I costruttori delle classi base devono sempre essere richiamati esplicitamente, poiché molto spesso è necessario passare argomenti speciali.
Esempio:
class Animal:
def __init__(self, type, name):
self.type = type
self.name = name
class Dog(Animal):
def __init__(self, name):
super().__init__("Cane", name) # Chiamata al costruttore della classe base
class Cat(Animal):
def __init__(self, name):
super().__init__("Gatto", name) # Chiamata al costruttore della classe base
# Creazione di un oggetto Dog
dog = Dog("Buddy")
print(dog)
In questo esempio, il costruttore della classe base (Animal)
ha due parametri: tipo di animale e nome. Le classi derivate invece ne hanno solo uno: il nome.
Nei costruttori delle classi Dog
e Cat
si decide cosa esattamente passare al costruttore della classe base — i nomi dei tipi di animali «Cane» e «Gatto».
Quindi:
- Il costruttore della classe base deve essere necessariamente richiamato nel costruttore della classe derivata.
- Per fare ciò, bisogna utilizzare il metodo
super()
. -
Non è necessario passare il parametro
self
separatamente — Python lo inserirà automaticamente alla chiamata del metodo.
7.3 Utilizzo del metodo super()
Il metodo super()
in Python può essere utilizzato non solo nei costruttori, ma anche in altri metodi delle classi per richiamare i metodi della classe genitore. Questo può essere utile quando è necessario estendere o modificare il comportamento di un metodo definito nella classe genitore.
Osserviamo alcuni esempi:
Richiamare un metodo della classe genitore in un metodo figlio
In questo esempio, il metodo speak()
nella classe Dog
chiama per primo il metodo speak()
della classe Animal
utilizzando super()
, quindi aggiunge il proprio comportamento.
class Animal:
def speak(self):
return "Some generic animal sound"
class Dog(Animal):
def speak(self):
parent_speech = super().speak() # Richiama il metodo della classe genitore
return f"{parent_speech} E il cane abbaia!"
dog = Dog()
print(dog.speak()) # Stamperà: Some generic animal sound E il cane abbaia!
Richiamare un metodo della classe genitore per verificare lo stato
In questo esempio, il metodo check_health()
nella classe Dog
chiama il metodo
check_health()
della classe Animal
per aggiungere controlli aggiuntivi.
class Animal:
def check_health(self):
return "Animal is healthy"
class Dog(Animal):
def check_health(self):
parent_check = super().check_health() # Richiama il metodo della classe genitore
return f"{parent_check}. Il cane ha bisogno di una passeggiata!"
dog = Dog()
print(dog.check_health()) # Stamperà: Animal is healthy. Il cane ha bisogno di una passeggiata!
Richiamare un metodo della classe genitore in un metodo che modifica lo stato
In questo esempio, il metodo withdraw()
nella classe SavingsAccount
verifica prima se il limite di prelievo è stato superato, e se non lo è, chiama il metodo withdraw()
della classe BankAccount
per eseguire l'operazione.
class BankAccount:
def __init__(self, balance):
self.balance = balance
def withdraw(self, amount):
if self.balance >= amount:
self.balance -= amount
return f"Withdrew {amount}. New balance: {self.balance}"
return "Fondi insufficienti"
class SavingsAccount(BankAccount):
def withdraw(self, amount):
if amount > 1000:
return "Limite di prelievo superato"
return super().withdraw(amount) # Richiamo del metodo della classe genitore
savings = SavingsAccount(1500)
print(savings.withdraw(500)) # Stamperà: Withdrew 500. New balance: 1000
print(savings.withdraw(1500)) # Stamperà: Limite di prelievo superato
GO TO FULL VERSION