Une classe abstraite PHP se déclare avec abstract class Name et ne peut pas être créée avec new. C'est une base pour d'autres classes : elle peut avoir des propriétés, un constructeur et des méthodes terminées, plus des méthodes abstract sans corps, que chaque classe enfant doit implémenter.
describe() est écrite une fois dans Shape et appelle area(), que fournit chaque enfant. La classe abstraite garantit que la méthode existe, donc describe() peut compter dessus.
On ne peut pas créer une classe abstraite avec new
Une classe abstraite est incomplète volontairement : Shape::area() n'a pas de corps, donc un simple objet Shape n'aurait rien à exécuter. PHP refuse d'en créer un et lève une Error :
Méthodes abstraites : les règles
Une méthode abstraite a une signature et un point-virgule au lieu d'un corps. Chaque enfant doit l'implémenter avec une signature compatible et une visibilité identique ou plus large : une méthode abstract protected peut devenir protected ou public dans l'enfant, jamais private. Une classe qui a ne serait-ce qu'une méthode abstraite doit elle-même être déclarée abstraite.
Un enfant qui oublie une méthode abstraite arrête le script avant qu'une seule ligne s'exécute, sauf si l'enfant est lui aussi déclaré abstrait et laisse la méthode à ses propres enfants :
PHP Fatal error: Class Square contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Shape::area) in /home/index.php on line 3
Le patron de méthode
La raison la plus courante d'écrire une classe abstraite : une suite d'étapes fixe dont quelques étapes diffèrent. La classe de base possède la suite dans une méthode final, et les enfants remplissent les étapes. Ici, le même rapport sort en texte brut et en tableau HTML :
Exécutez-le et l'onglet Page affiche le tableau HTML au-dessus de la version texte. open() et close() ont des corps par défaut, donc seul HtmlReport prend la peine de les redéfinir ; row() est abstraite car il n'y a pas de comportement par défaut raisonnable. Rendre render() final empêche un enfant de changer l'ordre des étapes.
Une classe abstraite peut implémenter une interface
Une classe abstraite peut déclarer implements et laisser certaines méthodes de l'interface à ses enfants. C'est la façon standard d'associer une interface (le type) à une classe de base (le code partagé) :
Le code type avec l'interface Cache, donc une classe qui ne peut pas étendre BaseCache (parce qu'elle étend déjà autre chose) peut toujours implémenter Cache directement.
Quand utiliser une classe abstraite, et quand ne pas le faire
Prenez une classe abstraite quand les classes d'une famille partagent du vrai code : propriétés, constructeur, méthodes identiques pour toutes. Si la base ne contiendrait que des méthodes abstraites, c'est une interface déguisée, et une interface est le meilleur choix, car une classe peut implémenter plusieurs interfaces mais n'étendre qu'une classe. Si vous voulez seulement partager quelques méthodes utilitaires entre des classes sans rapport, utilisez un trait au lieu de les forcer sous un même parent.
Un test rapide avant d'écrire abstract class : chaque enfant serait-il vraiment une sorte de la base (Circle est une Shape) ? Si la réponse honnête est « il sait faire ceci » plutôt que « il est l'un de ceux-là », écrivez une interface.
Questions fréquentes
Qu'est-ce qu'une classe abstraite en PHP ?
Une classe déclarée avec abstract class Name qui ne peut pas être créée avec new. C'est une base pour d'autres classes : elle peut contenir des propriétés, un constructeur et des méthodes normales, et peut déclarer des méthodes abstract que chaque classe enfant doit implémenter.
Qu'est-ce qu'une méthode abstraite en PHP ?
Une méthode déclarée avec abstract et sans corps : abstract protected function render(array $rows): string;. Une classe qui en contient une doit elle-même être déclarée abstract, et chaque classe enfant non abstraite doit définir une méthode avec une signature compatible.
Une classe abstraite peut-elle avoir un constructeur en PHP ?
Oui. Vous ne pouvez pas appeler new sur la classe abstraite, mais son constructeur s'exécute quand une classe enfant est créée, soit automatiquement (si l'enfant n'a pas de constructeur), soit via parent::__construct(...).
Peut-on instancier une classe abstraite en PHP ?
Non. new Shape() sur une classe abstraite lève une Error : Cannot instantiate abstract class Shape. Créez plutôt un objet d'une classe enfant concrète, par exemple new Circle(2).
Quand utiliser une classe abstraite en PHP ?
Quand plusieurs classes liées partagent du vrai code (propriétés, constructeur, méthodes communes) et diffèrent sur quelques étapes. Placez le code partagé dans la classe abstraite et déclarez abstraites les étapes qui diffèrent. S'il n'y a pas de code partagé et qu'il vous faut seulement un contrat, utilisez une interface.