abstract
In PHP, la parola chiave abstract definisce classi e metodi astratti. Una classe astratta non può essere istanziata ed è pensata per essere estesa.
La parola chiave abstract in PHP
La parola chiave abstract contrassegna una classe o un metodo come incompleto per scelta. Una classe astratta definisce una struttura comune e un comportamento condiviso, ma non può essere trasformata in un oggetto da sola — esiste per essere estesa. Un metodo astratto dichiara la firma di un metodo senza un corpo, costringendo ogni sottoclasse concreta a fornire l'implementazione effettiva.
Questa pagina tratta cosa sono le classi e i metodi astratti, come dichiararli, le regole che PHP impone e quando utilizzare abstract è la scelta progettuale giusta.
Cos'è una classe astratta?
Una classe astratta è una classe che non può essere istanziata direttamente. È pensata per essere estesa da altre classi che completano le parti mancanti. Una classe astratta può combinare due tipi di membri:
- Metodi astratti — dichiarati ma non implementati, lasciando il lavoro alle sottoclassi.
- Metodi e proprietà concreti — completamente implementati ed ereditati così come sono, in modo che la logica condivisa risieda in un unico posto.
La regola è unidirezionale: una classe con almeno un metodo astratto deve essere dichiarata abstract. Il contrario non è richiesto — una classe può essere astratta senza avere metodi astratti, semplicemente per impedire che venga istanziata.
<?php
abstract class Animal {
// Concrete method — inherited by every subclass unchanged
public function describe(): string {
return "I am a " . static::class . " and I say " . $this->makeSound();
}
// Abstract method — each subclass must implement it
abstract public function makeSound(): string;
}Cos'è un metodo astratto?
Un metodo astratto è dichiarato con la parola chiave abstract, non ha corpo e termina con un punto e virgola invece di { ... }. Il suo scopo è definire un contratto: qualsiasi sottoclasse che vuole essere concreta deve fornire un'implementazione corrispondente.
<?php
abstract public function makeSound(): string; // signature only, no bodyUna sottoclasse deve mantenere il metodo compatibile con la dichiarazione astratta — gli stessi parametri (o compatibili) e una visibilità uguale o meno restrittiva rispetto all'originale.
Come definire una classe e un metodo astratto
Inserire abstract prima di class per rendere la classe astratta, e prima di function per rendere un metodo astratto. Ecco il pattern completo — una classe base con un metodo condiviso e un metodo astratto, più due sottoclassi concrete:
<?php
abstract class Animal {
public function describe(): string {
return static::class . " says " . $this->makeSound();
}
abstract public function makeSound(): string;
}
class Dog extends Animal {
public function makeSound(): string {
return "Woof!";
}
}
class Cat extends Animal {
public function makeSound(): string {
return "Meow!";
}
}
echo (new Dog())->describe(), "\n"; // Dog says Woof!
echo (new Cat())->describe(), "\n"; // Cat says Meow!Ogni sottoclasse implementa makeSound() ed eredita describe() gratuitamente — quel metodo condiviso è esattamente il motivo per cui una classe base astratta è più utile di una semplice interfaccia in questo caso.
Cosa succede se si istanzia una classe astratta?
Tentare di creare un oggetto da una classe astratta è un errore fatale, rilevato in fase di compilazione:
<?php
abstract class Animal {
abstract public function makeSound(): string;
}
$a = new Animal();
// Fatal error: Cannot instantiate abstract class AnimalLo stesso errore si verifica se una sottoclasse dimentica di implementare un metodo astratto ereditato — PHP considera quella sottoclasse ancora astratta.
Regole e avvertenze
- Una classe con qualsiasi metodo astratto deve essere dichiarata
abstract. - I metodi astratti non possono essere
private— le sottoclassi non potrebbero vederli per sovrascriverli. Usarepublicoprotected. - I metodi astratti non possono essere
final(sono pensati per essere sovrascritti) e, a partire da PHP 8.0, non possono esserestaticin modo significativamente sovrascrivibile — preferire i metodi astratti di istanza. - Una classe astratta può avere un costruttore; le sottoclassi lo chiamano con
parent::__construct(). - Una sottoclasse che non implementa tutti i metodi astratti ereditati deve essa stessa essere dichiarata
abstract.
Classe astratta vs interfaccia
Entrambe definiscono un contratto, ma rispondono a domande diverse:
- Una classe astratta ("è-un") può contenere metodi concreti, proprietà e costruttori. Una classe può estendere solo una classe astratta.
- Un'interfaccia ("può-fare") dichiara solo le firme dei metodi (nessuna implementazione, nessuno stato di istanza) e una classe può implementare molte interfacce.
Scegliere una classe astratta quando le sottoclassi condividono un'implementazione reale; scegliere un'interfaccia quando è sufficiente garantire una capacità. Vedere PHP Inheritance e PHP Interfaces per ulteriori informazioni.
Conclusione
La parola chiave abstract consente di definire un progetto parziale: una classe astratta fornisce un comportamento condiviso dichiarando al contempo metodi astratti che ogni sottoclasse concreta deve implementare. Non è possibile istanziare una classe astratta direttamente — questo è lo scopo. Usarla quando diverse classi correlate condividono logica ma ciascuna deve personalizzare passaggi specifici, e scegliere invece un'interfaccia quando non è coinvolta alcuna implementazione condivisa.