Introduzione
In PHP, ereditarietà e polimorfismo sono due concetti fondamentali della programmazione orientata agli oggetti. L’ereditarietà ci permette di creare una classe base condivisa, mentre il polimorfismo ci consente di trattare oggetti diversi in modo uniforme, lasciando che ognuno esegua il proprio comportamento specifico.
In questo tutorial useremo un caso pratico e molto comune: la gestione di notifiche. Immagina un sistema che deve inviare messaggi tramite canali diversi: email, SMS e push notification. Ogni canale ha regole e dettagli propri, ma il flusso applicativo può restare lo stesso: creare una notifica e inviarla.
Questo scenario è perfetto per capire come progettare codice estendibile, leggibile e facile da mantenere. Invece di scrivere tanti if/else o switch sparsi nel progetto, possiamo affidare il comportamento a classi specializzate.
Codice completo
<?php
declare(strict_types=1);
/**
* Classe base astratta.
* Definisce la struttura comune a tutte le notifiche.
*/
abstract class Notification
{
public function __construct(
protected string $recipient
) {}
// Ogni notifica deve definire il proprio messaggio
abstract public function send(string $message): void;
// Metodo condiviso: utile a tutte le notifiche
protected function log(string $channel, string $message): void
{
echo "[{$channel}] Invio a {$this- Spiegazione
Vediamo il codice con calma. La classe Notification è una classe astratta: non viene istanziata direttamente, ma serve come base per le classi figlie. Contiene un dato comune, cioè il destinatario, e un metodo condiviso log(), utile a tutte le notifiche.
Il metodo send() è dichiarato come astratto. Questo significa che ogni classe figlia è obbligata a implementarlo. È una scelta molto utile quando vuoi imporre una “regola contrattuale” alle sottoclassi: tutte devono saper inviare un messaggio, ma ognuna lo farà a modo proprio.
Le classi EmailNotification, SmsNotification e PushNotification estendono la classe base e definiscono la propria versione di send(). Qui entra in gioco il polimorfismo: il metodo viene chiamato nello stesso modo, ma il comportamento cambia in base all’oggetto concreto.
La parte più interessante è NotificationService. Questo servizio riceve un array di oggetti Notification e li gestisce senza conoscere il tipo specifico. Per lui tutti gli oggetti sono “notifiche” e basta. Quando chiama $notification->send(), sarà PHP a decidere quale implementazione eseguire.
Questo approccio porta diversi vantaggi:
- il codice è più pulito e leggibile;
- aggiungere un nuovo canale, come WhatsApp, richiede solo una nuova classe;
- si riduce la logica condizionale basata su tipi o stringhe;
- il sistema è più facile da testare e mantenere.
Per esempio, se domani vuoi aggiungere WhatsAppNotification, non devi modificare il servizio. Ti basta creare una nuova classe che estende Notification e implementa send(). Questo è un ottimo esempio di estendibilità.
Best practice
- Usa l’ereditarietà solo quando esiste una vera relazione “è un”. Email, SMS e push sono tutti tipi di notifica, quindi l’ereditarietà ha senso.
- Preferisci classi astratte o interfacce per definire un contratto. Se vuoi imporre un comportamento comune, un metodo astratto è una soluzione chiara.
- Evita di mettere troppa logica nella classe base. La classe padre dovrebbe contenere solo ciò che è davvero condiviso.
- Non usare switch per gestire i tipi di oggetto. Se il comportamento cambia in base alla classe, lascia che sia il polimorfismo a gestirlo.
- Progetta pensando all’estensione, non alla modifica. Aggiungere nuovi canali dovrebbe essere semplice e non richiedere riscritture.
- Tipizza i metodi e usa strict_types. In PHP moderno, la tipizzazione aiuta a prevenire errori e rende il codice più affidabile.
Un altro consiglio importante: se la classe base inizia a diventare troppo complessa, forse stai forzando l’ereditarietà. In alcuni casi potrebbe essere più adatta una composizione, ma per questo scenario l’ereditarietà resta una scelta naturale e didatticamente efficace.
Riepilogo
In questo tutorial abbiamo visto come usare ereditarietà e polimorfismo in PHP attraverso un esempio concreto: la gestione di notifiche via email, SMS e push.
- La classe astratta Notification definisce la struttura comune.
- Le classi figlie implementano il metodo send() in modo specifico.
- Il servizio NotificationService usa il polimorfismo per inviare messaggi senza conoscere il tipo concreto dell’oggetto.
- Il risultato è un codice più ordinato, estendibile e facile da mantenere.
Se impari a riconoscere questi pattern, potrai progettare applicazioni PHP più solide e meno fragili quando i requisiti cambiano.
Approfondisci con risorse ufficiali
- PHP Manual - Classi e oggetti: https://www.php.net/manual/it/language.oop5.php
- PHP Manual - Classi astratte: https://www.php.net/manual/it/language.oop5.abstract.php
- PHP Manual - Tipizzazione: https://www.php.net/manual/it/language.types.declarations.php
- PHP Manual - Strict typing: https://www.php.net/manual/it/functions.arguments.php#functions.arguments.type-declaration.strict
