implements
Apprenez comment le mot-clé "implements" de PHP applique les contrats d'interface. Syntaxe, interfaces multiples, constantes et erreurs courantes.
Le mot-clé PHP implements
Le mot-clé implements indique à PHP qu'une classe s'engage à remplir le contrat défini par une interface. Une interface liste des signatures de méthodes (et éventuellement des constantes) mais pas de corps de méthode ; une classe qui l'implémente doit fournir un corps concret pour chaque méthode que l'interface déclare. Dans le cas contraire, PHP génère une erreur fatale avant l'exécution du programme.
Cette page couvre la syntaxe, l'implémentation de plusieurs interfaces à la fois, les constantes d'interface, le typage par interface, les erreurs courantes que vous rencontrerez, et la différence entre implements et extends. Si les interfaces sont nouvelles pour vous, commencez par PHP Interfaces et What is OOP.
Syntaxe
interface MyInterface {
public function doSomething(); // signature only — no body
}
class MyClass implements MyInterface {
public function doSomething() {
// the concrete implementation lives here
}
}MyClass implements MyInterface est une promesse : « cette classe fournit une version fonctionnelle de chaque méthode que MyInterface exige. » L'interface est le quoi ; la classe est le comment.
Un exemple de base
<?php
interface Animal {
public function makeSound();
}
class Dog implements Animal {
public function makeSound() {
echo "Woof!";
}
}
class Cat implements Animal {
public function makeSound() {
echo "Meow!";
}
}
$animals = [new Dog(), new Cat()];
foreach ($animals as $animal) {
$animal->makeSound(); // Output: Woof!Meow!
}Comme Dog et Cat implémentent toutes deux Animal, tout code qui attend un Animal peut fonctionner avec l'une ou l'autre sans connaître la classe concrète. C'est le fondement du polymorphisme en PHP.
Implémenter plusieurs interfaces
Contrairement à extends (une classe ne peut étendre qu'un seul parent), une classe peut implémenter autant d'interfaces qu'elle le souhaite — séparez-les par des virgules. La classe doit satisfaire toutes les méthodes de chaque interface qu'elle liste.
<?php
interface Logger {
public function log(string $message): void;
}
interface Notifier {
public function notify(string $message): void;
}
class AlertService implements Logger, Notifier {
public function log(string $message): void {
echo "LOG: $message\n";
}
public function notify(string $message): void {
echo "NOTIFY: $message\n";
}
}
$service = new AlertService();
$service->log("Disk space low"); // Output: LOG: Disk space low
$service->notify("Disk space low"); // Output: NOTIFY: Disk space lowC'est ainsi que PHP tire les avantages de l'héritage multiple (partager plusieurs contrats) sans ses inconvénients (implémentations héritées ambiguës).
Constantes d'interface et typage
Une interface peut déclarer des constantes, et une classe qui l'implémente y accède comme à ses propres constantes. La vraie puissance réside cependant dans le typage : lorsque vous typez un paramètre contre l'interface, toute classe qui l'implémente est acceptée — vous pouvez ainsi échanger librement les implémentations.
<?php
interface PaymentGateway {
const CURRENCY = "USD";
public function charge(float $amount): bool;
}
class StripeGateway implements PaymentGateway {
public function charge(float $amount): bool {
echo "Charging " . self::CURRENCY . " $amount\n";
return true;
}
}
// Accepts ANY PaymentGateway, not just StripeGateway
function processPayment(PaymentGateway $gateway, float $amount): void {
$gateway->charge($amount);
}
processPayment(new StripeGateway(), 49.99); // Output: Charging USD 49.99Vous pouvez également tester un objet par rapport à une interface à l'exécution avec instanceof :
var_dump($gateway instanceof PaymentGateway); // bool(true)Erreurs courantes et pièges
- Omettre une méthode est fatal. Si une classe omet ne serait-ce qu'une méthode d'interface, PHP génère
Fatal error: Class X contains 1 abstract method and must therefore be declared abstract or implement the remaining methods. La vérification se produit à la compilation, avant toute exécution du code. - Les signatures doivent être compatibles. Votre implémentation doit respecter les types de paramètres et de retour déclarés par l'interface (vous pouvez élargir les types de paramètres et réduire les types de retour selon les règles de variance de PHP, mais les incompatibilités sont fatales).
- Les méthodes d'interface sont implicitement
public. Vous ne pouvez pas implémenter une méthode d'interface enprotectedouprivate. - Les interfaces peuvent étendre d'autres interfaces. Utilisez
interface B extends Apour construire sur une autre interface ; une classe qui implémenteBdoit satisfaire les méthodes des deux. Notez que cela utiliseextends, pasimplements.
implements vs extends
Ces mots-clés peuvent prêter à confusion :
extends | implements | |
|---|---|---|
| Utilisé avec | une classe parente unique (ou interface→interface) | une ou plusieurs interfaces |
| Hérite du code ? | oui — propriétés et corps de méthodes | non — uniquement le contrat (signatures) |
| Combien ? | une classe étend une classe | une classe implémente plusieurs interfaces |
Une classe peut faire les deux à la fois : class Circle extends Shape implements JsonSerializable { ... }. Pour les détails sur l'héritage, voir PHP extends et, lorsque vous souhaitez des implémentations partielles, PHP abstract classes.
Quand utiliser implements
Utilisez une interface et implements lorsque :
- Plusieurs classes non liées doivent être interchangeables (par ex. plusieurs passerelles de paiement, loggers ou pilotes de cache).
- Vous souhaitez typer par capacité plutôt que par classe concrète, ce qui maintient le code faiblement couplé et facile à tester avec des mocks.
- Vous définissez un contrat d'API publique que d'autres classes — y compris celles écrites plus tard ou par d'autres équipes — doivent respecter.
Si vous avez plutôt besoin de partager du code d'implémentation réel entre des classes liées, utilisez l'héritage de classe (extends) ou une classe abstraite.