Menu
Coddy logo textTech

Classi e metodi astratti

Fa parte della sezione Programmazione orientata agli oggetti del percorso Python di Coddy. Lezione 25 di 64.

Le classi astratte sono classi che non possono essere istanziate direttamente e contengono metodi astratti che devono essere implementati dalle sottoclassi.

Immaginala come un modulo: una classe astratta è come un modulo obbligatorio in cui alcuni campi sono richiesti (metodi astratti) e altri sono facoltativi (metodi concreti). Non puoi inviare il modulo così com’è: devi prima compilare tutti i campi richiesti. Allo stesso modo, non puoi creare istanze di una classe astratta finché tutti i metodi astratti non sono implementati in una sottoclasse.

Importa il modulo abc per creare classi astratte:

from abc import ABC, abstractmethod

Crea una classe astratta con metodi astratti:

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass
    
    @abstractmethod
    def perimeter(self):
        pass
    
    def describe(self):
        return "This is a shape"  # Metodo concreto (ha un'implementazione)

Il decoratore @abstractmethod contrassegna i metodi che le sottoclassi devono implementare: sono i «campi obbligatori» del tuo modulo. I metodi normali, come describe(), possono avere un'implementazione e vengono ereditati così come sono: sono i «campi precompilati».

Perché usare le classi astratte? Impongono un contratto. Se crei una classe Shape, stai dicendo: "ogni forma DEVE essere in grado di calcolare la propria area e il proprio perimetro". Questo previene i bug che potrebbero verificarsi se ti dimenticassi di implementare metodi fondamentali.

Prova a creare un'istanza della classe astratta:

# Questo causerà un errore:
# shape = Shape()  # TypeError: Can't instantiate abstract class

Questo errore è intenzionale: è come cercare di inviare un modulo vuoto. Python sta dicendo: "Non hai ancora compilato i campi obbligatori (i metodi area e perimeter)!"

Crea una sottoclasse concreta che implementi tutti i metodi astratti:

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius
    
    def area(self):
        return 3.14 * self.radius ** 2
    
    def perimeter(self):
        return 2 * 3.14 * self.radius

Ora abbiamo "compilato tutti i campi obbligatori": abbiamo implementato sia area() sia perimeter(). La classe Circle è ora una classe concreta completa che può essere istanziata.

Ora puoi creare istanze della classe concreta:

circle = Circle(5)
print(circle.area())
print(circle.perimeter())
print(circle.describe())  # Metodo concreto ereditato

Crea un'altra sottoclasse concreta:

class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height
    
    def area(self):
        return self.width  self.height
    
    def perimeter(self):
        return 2 * (self.width + self.height)

rectangle = Rectangle(4, 6)
print(rectangle.area())
print(rectangle.perimeter())

Output:

78.5
31.400000000000002
This is a shape
24
20

Le classi astratte definiscono un contratto che le sottoclassi devono rispettare. Usa ABC e @abstractmethod per creare classi astratte. Le sottoclassi devono implementare tutti i metodi astratti, altrimenti saranno anch'esse astratte. Questo garantisce la coerenza e previene implementazioni incomplete.

challenge icon

Sfida

Medio

In questa sfida, implementerai un sistema di elaborazione dei pagamenti.

Devi completare l’implementazione in questi file:

  • paymentmethod.py - Classe base astratta con logica di convalida
  • creditcard.py - Implementazione del pagamento con carta di credito
  • paypal.py - Implementazione del pagamento con PayPal

Segui i commenti TODO in ogni file per implementare le funzionalità richieste. I commenti ti guideranno passo dopo passo nella creazione di metodi astratti, nell’implementazione di sottoclassi concrete e nella definizione delle corrette relazioni di importazione tra i file.

Il file driver.py contiene casi di test che verificheranno che la tua implementazione funzioni correttamente, elaborando diversi scenari di pagamento e visualizzando i dettagli appropriati per ogni metodo di pagamento.

Provalo tu

from creditcard import CreditCard
from paypal import PayPal

# Testa le implementazioni - NON MODIFICARE QUESTO CODICE DI TEST
cc = CreditCard("1234567890123456")
pp = PayPal("user@example.com")

# Elabora i pagamenti validi
if cc.validate(100):
    print(cc.process_payment(100))
    print(cc.payment_details())

if pp.validate(200):
    print(pp.process_payment(200))
    print(pp.payment_details())

# Prova un importo non valido
if not pp.validate(0):
    print("Invalid payment amount")

# Questo genererebbe un errore se venisse rimosso il commento:
# pm = PaymentMethod()  # Non è possibile istanziare una classe astratta
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore Python online