Menu
Coddy logo textTech

Polymorphisme via les interfaces

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

Dans la leçon précédente, tu as découvert le polymorphisme par héritage, où les classes enfants redéfinissent les méthodes parentes. Les interfaces offrent une autre manière puissante de mettre en œuvre le polymorphisme, en particulier lorsque tu travailles avec des classes sans lien qui partagent un comportement commun.

Avec les interfaces, le polymorphisme découle du contrat lui-même. Toute classe qui implémente une interface garantit qu’elle possède certaines méthodes, quelle que soit sa hiérarchie d’héritage :

<?php
interface Notifiable {
    public function send(string $message);
}

class EmailNotifier implements Notifiable {
    public function send(string $message) {
        return "Email: " . $message;
    }
}

class SMSNotifier implements Notifiable {
    public function send(string $message) {
        return "SMS: " . $message;
    }
}

class PushNotifier implements Notifiable {
    public function send(string $message) {
        return "Push: " . $message;
    }
}

function notify(Notifiable $notifier, string $message) {
    return $notifier->send($message);
}

echo notify(new EmailNotifier(), "Hello") . "\n";
echo notify(new SMSNotifier(), "Hello") . "\n";
echo notify(new PushNotifier(), "Hello");

Sortie :

Email: Hello
SMS: Hello
Push: Hello

La fonction notify() fonctionne avec n’importe quel objet Notifiable. Ces classes ne partagent pas de classe parente : elles sont complètement indépendantes, à l’exception du fait qu’elles implémentent la même interface. C’est le principal avantage par rapport au polymorphisme fondé sur l’héritage : vous pouvez regrouper des classes indépendantes selon leurs capacités plutôt que selon leur ascendance.

Point clé : Le polymorphisme fondé sur les interfaces permet d’utiliser des classes sans lien entre elles de manière interchangeable en fonction d’un comportement commun, ce qui rend votre code plus flexible et moins couplé à des implémentations spécifiques.

challenge icon

Défi

Facile

Construisons un système de stockage qui démontre le polymorphisme basé sur les interfaces. Tu vas créer différents systèmes de stockage, un système de fichiers et une base de données, qui n'ont rien en commun si ce n'est qu'ils implémentent tous deux la même interface de stockage. Une seule fonction fonctionnera avec n'importe quel type de stockage, montrant ainsi comment les interfaces permettent le polymorphisme entre des classes totalement indépendantes.

Tu organiseras ton code sur quatre fichiers :

  • Storable.php : définis une interface Storable avec deux signatures de méthodes : save($key, $data) et retrieve($key). Ce contrat garantit que tout système de stockage peut enregistrer et récupérer des données, quelle que soit son implémentation interne.
  • FileStorage.php : crée une classe FileStorage qui implémente Storable. Inclus le fichier de l'interface. La classe doit avoir une propriété privée $directory définie par le constructeur. Implémente save($key, $data) pour retourner "Saving '[data]' to file [directory]/[key].txt". Implémente retrieve($key) pour retourner "Reading from file [directory]/[key].txt".
  • DatabaseStorage.php : crée une classe DatabaseStorage qui implémente également Storable. Inclus le fichier de l'interface. La classe doit avoir une propriété privée $tableName définie par le constructeur. Implémente save($key, $data) pour retourner "Inserting '[data]' into table [tableName] with key [key]". Implémente retrieve($key) pour retourner "Selecting from table [tableName] where key = [key]".
  • main.php : inclus les deux fichiers de stockage. Crée une fonction appelée storeData qui accepte un paramètre de type Storable, une clé et des données. La fonction doit retourner le résultat de l'appel à save() avec la clé et les données. Crée une autre fonction appelée fetchData qui accepte un paramètre de type Storable et une clé, et retourne le résultat de l'appel à retrieve().

Tu recevras quatre entrées : un chemin de répertoire, un nom de table, une clé et des données à stocker. Crée un FileStorage avec le répertoire et un DatabaseStorage avec le nom de la table. Utilise ta fonction storeData() pour enregistrer les données d'abord avec le stockage de fichiers, puis avec le stockage de base de données. Affiche chaque résultat sur sa propre ligne. Ensuite, utilise fetchData() pour récupérer les données depuis le stockage de fichiers et affiche ce résultat.

Remarque comme storeData() et fetchData() fonctionnent de manière identique avec les deux types de stockage. Elles se soucient uniquement du fait que l'objet implémente Storable. Le système de fichiers et la base de données ont des implémentations internes complètement différentes, mais ils sont interchangeables grâce au contrat de l'interface.

Essayez vous-même

<?php
require_once 'FileStorage.php';
require_once 'DatabaseStorage.php';

// Lire les entrées
$directory = trim(fgets(STDIN));
$tableName = trim(fgets(STDIN));
$key = trim(fgets(STDIN));
$data = trim(fgets(STDIN));

// TODO: Créer une fonction storeData qui accepte un Storable, key et data
// Elle doit retourner le résultat de l'appel à save() avec la key et data

// TODO: Créer une fonction fetchData qui accepte un Storable et key
// Elle doit retourner le résultat de l'appel à retrieve() avec la key

// TODO: Créer une instance de FileStorage avec le directory

// TODO: Créer une instance de DatabaseStorage avec le table name

// TODO: Utiliser storeData() pour sauvegarder data avec le stockage fichier, puis afficher le résultat

// TODO: Utiliser storeData() pour sauvegarder data avec le stockage base de données, puis afficher le résultat

// TODO: Use fetchData() to retrieve from file storage, then print the result
?>
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