Sostieni AppuntiFacili con una piccola donazione su PayPal

Dona con PayPal
AppuntiFacili
Torna Indietro Segnala errore

Ereditarietà in Python

✍️ Dennis Turco 🏷️ Informatica 📘 Python
Ultima modifica:
#python#programmazione#oop#ereditarietà#classi

1. Introduzione

inheritance

L’ereditarietà (inheritance) è un principio fondamentale della programmazione orientata agli oggetti (OOP). Consente di riutilizzare e estendere il codice di una classe già esistente.

L’idea è semplice: una classe figlia (o sottoclasse) eredita attributi e metodi da una classe madre (o superclasse), potendo eventualmente modificarli o aggiungerne di nuovi.

INFO

L’ereditarietà promuove il riuso del codice e la manutenibilità, riducendo la duplicazione e rendendo il programma più modulare.

2. Creare una classe base e una classe derivata

animal-inheritance

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

    def parla(self):
        print("L'animale emette un suono.")

Ora creiamo una classe derivata che eredita da Animale:

class Cane(Animale):
    def parla(self):
        print("Bau!")

Uso:

a = Animale("Creatura")
c = Cane("Fido")

a.parla()   # L'animale emette un suono.
c.parla()   # Bau!

TIP

Se un metodo è definito sia nella classe base che nella classe derivata, Python usa quello della sottoclasse. Questo meccanismo si chiama override.

3. Il costruttore e la funzione super()

Quando una sottoclasse ha un proprio costruttore __init__, può comunque richiamare quello della classe base tramite super().

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

class Cane(Animale):
    def __init__(self, nome, razza):
        super().__init__(nome)     # chiama il costruttore della superclasse
        self.razza = razza

Uso:

c = Cane("Fido", "Labrador")
print(c.nome, c.razza) # Output: Fido Labrador

INFO

super() permette di accedere ai metodi della superclasse, ed è il modo corretto per evitare errori di duplicazione o sovrascrittura involontaria.

4. Aggiungere nuovi metodi o estendere quelli esistenti

Le sottoclassi possono aggiungere nuovi metodi oppure estendere quelli ereditati.

class Animale:
    def parla(self):
        print("Suono generico.")

class Cane(Animale):
    def parla(self):
        super().parla()      # chiama il metodo originale
        print("Bau!")

c = Cane()
c.parla()

Output:

Suono generico.
Bau!

5. Verificare relazioni di ereditarietà

In Python una classe può ereditare da più superclassi. È una caratteristica potente, ma da usare con attenzione.

class Volante:
    def vola(self):
        print("Sto volando!")

class Nuotante:
    def nuota(self):
        print("Sto nuotando!")

class Anatra(Volante, Nuotante):
    pass

a = Anatra()
a.vola()
a.nuota()

Output:

Sto volando!
Sto nuotando!

WARNING

In caso di conflitti (metodi con lo stesso nome in più superclassi), Python risolve automaticamente l’ordine di ricerca con la MRO (Method Resolution Order).

7. La MRO (Method Resolution Order)

La MRO definisce l’ordine in cui Python cerca un attributo o metodo nelle classi coinvolte nell’ereditarietà multipla.

Possibile visualizzarla con:

print(Anatra.mro())

Output (esempio):

[<class '__main__.Anatra'>, <class '__main__.Volante'>, <class '__main__.Nuotante'>, <class 'object'>]

8. Classi astratte

A volte vogliamo definire una classe base che non sia istanziabile, ma che serva solo da modello per altre classi. In Python si possono creare usando il modulo abc.

from abc import ABC, abstractmethod

class Animale(ABC):
    @abstractmethod
    def parla(self):
        pass

class Cane(Animale):
    def parla(self):
        print("Bau!")

Uso:

c = Cane()
c.parla()

INFO

Una classe astratta:

  • non può essere istanziata direttamente;
  • può definire metodi “vuoti” che devono essere implementati nelle sottoclassi.

9. Quiz a risposta multipla

1) In Python, cosa rappresenta l'ereditarietà?

2) Qual è la parola chiave usata per creare una sottoclasse in Python?

3) Cosa fa la funzione super() in una sottoclasse?

4) Se una sottoclasse ridefinisce un metodo della superclasse, cosa succede?

5) Come si definisce una classe astratta in Python?

6) Quale tra questi metodi serve per verificare se un oggetto appartiene a una classe o sottoclasse?

7) In un'ereditarietà multipla, come decide Python l'ordine di ricerca dei metodi?

8) Quale delle seguenti affermazioni sul polimorfismo è corretta?

9) Cosa restituisce la chiamata print(ClasseFiglia.mro())?

10) Quando è opportuno usare una classe astratta?

10. Esercizi

10.1 Esercizio

Creare una gerarchia di classi che rappresenti veicoli:

  • Classe base Veicolo con attributo marca e metodo info().
  • Classe Auto che eredita da Veicolo e aggiunge porte.
  • Classe Moto che eredita da Veicolo e aggiunge cilindrata.
  • Sovrascrivere info() in entrambe le sottoclassi per mostrare informazioni specifiche.
  • Creare alcune istanze e verifica l’uso di isinstance() e issubclass().

10.2 Esercizio — Gestione di un Parco Veicoli Aziendale

Creare un programma orientato agli oggetti che gestisca diversi tipi di veicoli, sfruttando ereditarietà, polimorfismo e classi astratte.

Specifiche:

  • Creare una classe base astratta Veicolo con:

    • attributi: marca, modello, anno, targa
    • metodo descrizione() che restituisce una stringa con le informazioni del veicolo
    • metodo eta() che calcola l’età come differenza tra la data attuale e l’anno di immatricolazione
    • metodo astratto calcola_costo_manutenzione()
  • Creare le sottoclassi:

    • Auto → aggiunge numero_porte e tipo_carburante
    • Moto → aggiunge cilindrata
    • Camion → aggiunge portata_massima
  • In ciascuna sottoclasse:

    • Sovrascrivere calcola_costo_manutenzione() con formule diverse
      • Auto: 100 + 10 * età
      • Moto: 80 + 5 * età
      • Camion: 200 + 20 * età
    • Ridefinire descrizione() per includere gli attributi specifici
  • Creare una classe ParcoVeicoli che:

    • Contenga una lista di veicoli
    • Permetta di aggiungere nuovi veicoli (aggiungi_veicolo())
    • Stampi tutti i veicoli con stampa_veicoli()
    • Calcoli il costo totale di manutenzione annuale
    • Ordini i veicoli in base al costo di manutenzione
  • Aggiungere un metodo di classe numero_veicoli() nella classe base per contare quanti veicoli sono stati creati.

Suggerimento:

Usare il modulo datetime per calcolare l’età dei veicoli

Prenota una lezione