
Classi astratte in Python
In questa lezione impariamo a usare le classi astratte nel linguaggio Python.
Cos'è una classe astratta? Una classe astratta è una classe che non puoi istanziare direttamente. Ti serve come modello per definire l'interfaccia di altre classi. In altre parole, una classe astratta definisce i metodi (detti metodi astratti) che devono essere obbligatoriamente implementati dalle classi derivate. In questo modo, tutte le sottoclassi sono obbligate a rispettare la stessa interfaccia comune.
Le classi astratte ti permettono di definire una struttura chiara su come dovrebbero essere implementate le classi derivate.
In altre parole, forzano le sottoclassi a implementare dei metodi specifici.
Come definire una classe astratta in Python?
In Python, puoi creare classi astratte usando il modulo `abc` (Abstract Base Classes). Ecco come fare:
from abc import ABC, abstractmethod
Una volta importato il modulo, puoi definire una classe astratta e i suoi metodi astratti.
class ClasseAstratta(ABC):
@abstractmethod
def metodo_astratto(self):
pass
Tutte le classi che ereditano da questa classe base astratta devono implementare il metodo definito come astratto.
Questo garantisce che tutte le sottoclassi avranno un'interfaccia comune.
Esempio pratico
Immagina che tu stia progettando un sistema per gestire diversi tipi di animali in un gioco.
Vuoi assicurarti che ogni animale abbia alcune funzionalità di base, come mangiare e dormire, ma ogni animale dovrebbe implementare queste funzionalità in modo diverso.
Per prima cosa, devi definire una classe astratta e i suoi metodi.
Ad esempio, definisci la classe astratta 'Animale' che contiene due metodi astratti: mangiare() e dormire()
class Animale(ABC):
@abstractmethod
def mangiare(self):
pass
@abstractmethod
def dormire(self):
pass
Entrambi i metodi sono astratti perché non sono preceduti da @abstractmethod.
Supponi di voler implementare due classi derivate: `Gatto` e `Cane`.
Entrambe le classi devono implementare i metodi `mangiare` e `dormire`.
class Gatto(Animale):
def mangiare(self):
print("Il gatto mangia croccantini.")
def dormire(self):
print("Il gatto dorme nel cesto.")
class Cane(Animale):
def mangiare(self):
print("Il cane mangia carne.")
def dormire(self):
print("Il cane dorme nella cuccia.")
Ora puoi creare istanze di `Gatto` e `Cane` e utilizzare i loro metodi.
Ad esempio, crea un'istanza della classe Gatto
gatto = Gatto()
Poi chiama il metodo mangiare()
gatto.mangiare()
Il gatto mangia croccantini.
Chiama anche il metodo dormire()
gatto.dormire()
Il gatto dorme nel cesto.
Ora crea un'istanza della classe Cane.
cane = Cane()
Poi chiama il metodo mangiare()
cane.mangiare()
Il cane mangia carne.
E il metodo dormire()
cane.dormire()
Il cane dorme nella cuccia.
Entrambe le classi hanno gli stessi metodi ma diverse implementazioni ovvero hanno la stessa interfaccia.
Tuttavia, non puoi creare un'istanza di `Animale` direttamente, perché è una classe astratta.
Se provi a instanziare direttamente la classe astratta, questo genererà un errore
animale = Animale()
TypeError: Can't instantiate abstract class Animale with abstract methods dormire, mangiare
Aggiunta di metodi concreti
Le classi astratte possono anche contenere metodi concreti (cioè metodi con un'implementazione).
Ad esempio, puoi aggiungere un metodo `descrizione` che fornisce una descrizione generica dell'animale.
class Animale(ABC):
@abstractmethod
def mangiare(self):
pass
@abstractmethod
def dormire(self):
pass
def descrizione(self):
print("Questo è un animale.")
In questo esempio il metodo descrizione() non è un metodo astratto perché non è preceduto da @abstractmethod.
Poi crea due sottoclassi derivate dalla classe astratta 'Animale'
La sottoclasse 'Gatto'
class Gatto(Animale):
def mangiare(self):
print("Il gatto mangia croccantini.")
def dormire(self):
print("Il gatto dorme nel cesto.")
La sottoclasse 'Cane'
class Cane(Animale):
def mangiare(self):
print("Il cane mangia carne.")
def dormire(self):
print("Il cane dorme nella cuccia.")
Ora crea un'istanza della classe 'Gatto'
gatto = Gatto()
Poi chiama il metodo descrizione()
gatto.descrizione()
Questo è un animale.
Il metodo descrizione() viene eseguito anche se non è implementato perché non è un metodo astratto.
Lo stesso accade se crei un'istanza dalla classe 'Cane'
cane = Cane()
E poi chiami il metodo descrizione() viene eseguito lo stesso metodo
cane.descrizione()
Questo è un animale.
In conclusione, le classi astratte ti forniscono un modo per definire un'interfaccia comune per un gruppo di classi correlate e assicurano che queste classi implementino metodi specifici.
Usandole correttamente, puoi creare sistemi che sono facili da comprendere, estendere e mantenere.
Spero che questa guida ti sia stata utile! Se hai altre domande o vuoi approfondire qualche argomento, fammelo sapere!