Vai al contenuto
eLearner.app
Modulo 7 · Lezione 2 di 426/36 nel corso~12 min
Lezioni del modulo (2/4)

Ereditarietà

L'ereditarietà ti permette di creare una nuova classe (la sottoclasse) che eredita attributi e metodi da una classe esistente (la classe base), e li può estendere o sovrascrivere.

Sintassi base

Python
class Animale:
    def __init__(self, nome):
        self.nome = nome

    def saluta(self):
        return f"{self.nome} fa un verso"

class Cane(Animale):       # Cane EREDITA da Animale
    def saluta(self):       # OVERRIDE del metodo
        return f"{self.nome} dice WOOF!"

a = Animale("X")
c = Cane("Fido")
a.saluta()      # 'X fa un verso'
c.saluta()      # 'Fido dice WOOF!'

Cane eredita __init__ da Animale senza riscriverlo.

super(): chiamare il metodo della base

Quando vuoi estendere un metodo della base (non sostituirlo completamente), usa super():

Python
class Animale:
    def __init__(self, nome):
        self.nome = nome

class Cane(Animale):
    def __init__(self, nome, razza):
        super().__init__(nome)    # delega alla base
        self.razza = razza

c = Cane("Fido", "Labrador")
c.nome        # 'Fido'
c.razza       # 'Labrador'

isinstance: controllo del tipo

Python
isinstance(c, Cane)        # True
isinstance(c, Animale)     # True (anche la base)
isinstance(c, str)         # False

isinstance(x, ClasseBase) riconosce anche tutte le sottoclassi: questo è ciò che rende l'ereditarietà utile per il polimorfismo.

Python
animali = [Cane("Fido", "X"), Animale("Pippo")]
for a in animali:
    print(a.saluta())        # ogni oggetto risponde a suo modo

MRO (Method Resolution Order) — cenni

Quando hai ereditarietà multipla, Python decide in che ordine cercare un metodo seguendo l'MRO, calcolato con l'algoritmo C3. Per il 95% dei casi basta sapere:

  1. cerca prima nell'istanza,
  2. poi nella sua classe,
  3. poi nelle classi base in ordine di dichiarazione.
Python
Cane.__mro__
# (<class 'Cane'>, <class 'Animale'>, <class 'object'>)

object è la radice di ogni classe in Python 3.

Ereditarietà multipla e MRO

A differenza di altri linguaggi (es. Java o C#), Python supporta l'ereditarietà multipla: una classe può ereditare contemporaneamente da più classi madri. L'ordine di risoluzione dei metodi viene gestito tramite un algoritmo chiamato MRO (Method Resolution Order), verificabile richiamando MiaClasse.mro().

Prova tu

Esercizio#python.m7.l2.e1
Tentativi: 0Caricamento…

Data `class Vehicle: def __init__(self, brand): self.brand = brand`, definisci `Car(Vehicle)` con __init__(self, brand, model) che chiama super().__init__ e salva self.model. Crea `a = Car('Fiat', '500')` e valuta `(a.brand, a.model)`.

Caricamento editor…
Mostra suggerimento

super().__init__(brand) poi self.model = model.

Soluzione disponibile dopo 3 tentativi

Esercizio di ripasso

Esercizio#python.m7.l2.e2
Tentativi: 0Caricamento…

Definisci `class Shape: def area(self): return 0` e `class Square(Shape)` con __init__(self, side) e area() che restituisce side * side. Crea `q = Square(5)` e valuta la tupla `(q.area(), isinstance(q, Shape))`.

Caricamento editor…
Mostra suggerimento

self.side * self.side.

Soluzione disponibile dopo 3 tentativi

Sfida aggiuntiva

Esercizio#python.m7.l2.e3
Tentativi: 0Caricamento…

Crea una classe `Square` che erediti dalla classe `Rectangle` (definita sotto). Il costruttore di `Square` deve accettare un singolo parametro `side` e passarlo a `super().__init__(side, side)`. Istanzia un quadrato con lato `6` salvandolo in `sq` e valuta `sq.area()`.

Caricamento editor…
Mostra suggerimento

Dichiara class Square(Rectangle): e chiama super().__init__(side, side) nel costruttore.

Soluzione disponibile dopo 3 tentativi