Menu
Coddy logo textTech

Interface ou classe abstraite

Fait partie de la section Programmation Orientée Objet du Journey PHP de Coddy. Leçon 30 sur 91.

Maintenant que tu as appris les interfaces et les classes abstraites, clarifions quand utiliser chacune d’elles. Bien qu’elles puissent sembler similaires, elles servent des objectifs différents et possèdent des capacités distinctes.

Fonctionnalité Interface Classe abstraite
Méthodes Uniquement les signatures de méthodes À la fois des méthodes abstraites et concrètes
Propriétés Uniquement des constantes Peut avoir des propriétés
Héritage multiple Une classe peut en implémenter plusieurs Une classe ne peut en étendre qu’une seule
Constructeur Peut déclarer une signature __construct (sans corps) Peut définir un constructeur avec un corps

Utilisez une interface lorsque vous souhaitez définir un contrat que des classes sans lien peuvent respecter. Par exemple, un Printer et un Logger peuvent tous deux implémenter une interface Writable, même s’ils ne partagent aucun ancêtre commun.

Utilisez une classe abstraite lorsque vous avez des classes apparentées qui partagent du code commun. Si vos classes Dog et Cat ont toutes deux besoin de la même implémentation de la méthode eat(), une classe abstraite Animal vous permet d’écrire ce code une seule fois.

Vous pouvez également combiner les deux approches. Une classe peut étendre une classe abstraite tout en implémentant plusieurs interfaces :

<?php
abstract class Animal {
    protected $name;
    
    public function eat() {
        return $this->name . " is eating";
    }
}

interface Swimmable {
    public function swim();
}

class Duck extends Animal implements Swimmable {
    public function __construct($name) {
        $this->name = $name;
    }
    
    public function swim() {
        return $this->name . " is swimming";
    }
}

Point clé : Choisissez les interfaces pour définir des capacités entre des classes sans lien. Choisissez les classes abstraites lorsque vous devez partager du code entre des classes apparentées.

challenge icon

Défi

Facile

Construisons un système de véhicules qui montre quand utiliser une classe abstraite plutôt qu'une interface, et comment combiner efficacement ces deux approches.

Vous allez créer un système dans lequel les véhicules partagent des propriétés communes grâce à l'héritage, mais peuvent également acquérir des capacités supplémentaires grâce aux interfaces. Cela reflète les décisions de conception du monde réel : une voiture « est un » véhicule (héritage), mais elle « possède également la capacité » d'être ravitaillée en carburant (interface).

Organisez votre code sur quatre fichiers :

  • Refuelable.php : définissez une interface Refuelable avec une seule signature de méthode : refuel($amount). Cette capacité peut s'appliquer à toute classe qui nécessite un ravitaillement, quelle que soit sa hiérarchie d'héritage.
  • Vehicle.php : définissez une classe abstraite Vehicle qui fournit les fonctionnalités communes à tous les véhicules. Elle doit posséder une propriété $brand protégée et une propriété $fuelLevel protégée (initialisée à 0). Le constructeur accepte le nom de la marque. Incluez une méthode concrète getBrand() qui renvoie la marque, une méthode concrète getFuelLevel() qui renvoie le niveau de carburant actuel, ainsi qu'une méthode abstraite drive() que les classes enfants doivent implémenter.
  • Car.php : créez une classe Car qui étend Vehicle et implémente Refuelable. Incluez les deux fichiers requis au début. Le constructeur accepte la marque et la transmet au constructeur parent. Implémentez drive() pour renvoyer "[brand] car is driving". Implémentez refuel($amount) pour ajouter la quantité au niveau de carburant et renvoyer "[brand] refueled to [fuelLevel] liters".
  • main.php : incluez le fichier Car. Vous recevrez deux entrées : un nom de marque et une quantité de carburant (à convertir en entier). Créez une Car avec la marque. Affichez le résultat de drive() sur la première ligne, puis affichez le résultat de refuel() avec la quantité de carburant sur la deuxième ligne.

Ce défi illustre la distinction essentielle : la classe abstraite Vehicle partage du code et établit une relation « est un », tandis que l'interface Refuelable ajoute une capacité qui pourrait s'appliquer à d'autres classes sans lien (comme un générateur ou un bateau), sans les obliger à être des véhicules.

Essayez vous-même

<?php
require_once 'Car.php';

// Lire l'entrée
$brand = trim(fgets(STDIN));
$fuelAmount = intval(trim(fgets(STDIN)));

// TODO: Créer une Car avec la marque

// TODO: Afficher le résultat de drive() sur la première ligne

// TODO: Afficher le résultat de refuel() avec la quantité de carburant sur la deuxième ligne
?>
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation Orientée Objet

Entraînez-vous par vous-même : Compilateur PHP en ligne