Menu
Coddy logo textTech

Polymorphie über Schnittstellen

Teil des Abschnitts Objektorientierte Programmierung der PHP-Journey von Coddy. Lektion 34 von 91.

In der vorherigen Lektion hast du Polymorphie durch Vererbung kennengelernt, bei der Kindklassen Methoden der Elternklassen überschreiben. Interfaces bieten eine weitere leistungsstarke Möglichkeit, Polymorphie zu erreichen, insbesondere bei der Arbeit mit nicht verwandten Klassen, die ein gemeinsames Verhalten aufweisen.

Bei Schnittstellen entsteht Polymorphie aus dem Vertrag selbst. Jede Klasse, die eine Schnittstelle implementiert, garantiert, dass sie bestimmte Methoden besitzt, unabhängig von ihrer Vererbungshierarchie:

<?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");

Ausgabe:

Email: Hello
SMS: Hello
Push: Hello

Die Funktion notify() funktioniert mit jedem Notifiable-Objekt. Diese Klassen haben keine gemeinsame übergeordnete Klasse – sie sind völlig unabhängig voneinander, abgesehen davon, dass sie dieselbe Schnittstelle implementieren. Dies ist der entscheidende Vorteil gegenüber der vererbungsbasierten Polymorphie: Du kannst unabhängige Klassen nach ihren Fähigkeiten statt nach ihrer Abstammung gruppieren.

Wichtiger Punkt: Schnittstellenbasierter Polymorphismus ermöglicht es, unabhängige Klassen aufgrund ihres gemeinsamen Verhaltens austauschbar zu verwenden, wodurch dein Code flexibler und von spezifischen Implementierungen entkoppelt wird.

challenge icon

Aufgabe

Einfach

Lass uns ein Speichersystem entwickeln, das polymorphes Verhalten auf Basis eines Interfaces demonstriert. Du wirst verschiedene Speicher-Backends erstellen, ein Dateisystem und eine Datenbank, die nichts gemeinsam haben, außer dass sie beide dasselbe Speicher-Interface implementieren. Eine einzelne Funktion wird mit jedem Speichertyp funktionieren und zeigen, wie Interfaces Polymorphismus zwischen vollständig unabhängigen Klassen ermöglichen.

Du wirst deinen Code auf vier Dateien verteilen:

  • Storable.php: Definiere ein Storable-Interface mit zwei Methodensignaturen: save($key, $data) und retrieve($key). Dieser Vertrag stellt sicher, dass jedes Speichersystem Daten speichern und abrufen kann, unabhängig davon, wie es intern implementiert ist.
  • FileStorage.php: Erstelle eine FileStorage-Klasse, die Storable implementiert. Binde die Interface-Datei ein. Die Klasse soll eine private Eigenschaft $directory besitzen, die über den Konstruktor festgelegt wird. Implementiere save($key, $data), sodass "Saving '[data]' to file [directory]/[key].txt" zurückgegeben wird. Implementiere retrieve($key), sodass "Reading from file [directory]/[key].txt" zurückgegeben wird.
  • DatabaseStorage.php: Erstelle eine DatabaseStorage-Klasse, die ebenfalls Storable implementiert. Binde die Interface-Datei ein. Die Klasse soll eine private Eigenschaft $tableName besitzen, die über den Konstruktor festgelegt wird. Implementiere save($key, $data), sodass "Inserting '[data]' into table [tableName] with key [key]" zurückgegeben wird. Implementiere retrieve($key), sodass "Selecting from table [tableName] where key = [key]" zurückgegeben wird.
  • main.php: Binde beide Speicherdateien ein. Erstelle eine Funktion namens storeData, die einen Storable-Parameter, einen Schlüssel und Daten akzeptiert. Die Funktion soll das Ergebnis des Aufrufs von save() mit dem Schlüssel und den Daten zurückgeben. Erstelle eine weitere Funktion namens fetchData, die einen Storable-Parameter und einen Schlüssel akzeptiert und das Ergebnis des Aufrufs von retrieve() zurückgibt.

Du erhältst vier Eingaben: einen Verzeichnispfad, einen Tabellennamen, einen Schlüssel und einige zu speichernde Daten. Erstelle ein FileStorage mit dem Verzeichnis und ein DatabaseStorage mit dem Tabellennamen. Verwende deine Funktion storeData(), um die Daten zuerst mit dem Dateispeicher und anschließend mit dem Datenbankspeicher zu speichern. Gib jedes Ergebnis in einer eigenen Zeile aus. Verwende dann fetchData(), um Daten aus dem Dateispeicher abzurufen, und gib dieses Ergebnis aus.

Beachte, wie storeData() und fetchData() mit beiden Speichertypen identisch funktionieren. Sie berücksichtigen nur, dass das Objekt Storable implementiert. Das Dateisystem und die Datenbank verfügen über völlig unterschiedliche interne Implementierungen, sind durch den Interface-Vertrag jedoch austauschbar.

Probier es selbst

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

// Eingaben lesen
$directory = trim(fgets(STDIN));
$tableName = trim(fgets(STDIN));
$key = trim(fgets(STDIN));
$data = trim(fgets(STDIN));

// TODO: Erstelle eine Funktion storeData, die ein Storable, key und data akzeptiert
// Sie sollte das Ergebnis des Aufrufs von save() mit dem key und data zurückgeben

// TODO: Erstelle eine Funktion fetchData, die ein Storable und key akzeptiert
// Sie sollte das Ergebnis des Aufrufs von retrieve() mit dem key zurückgeben

// TODO: Erstelle eine FileStorage-Instanz mit dem directory

// TODO: Erstelle eine DatabaseStorage-Instanz mit dem table name

// TODO: Verwende storeData(), um Daten mit Dateispeicher zu speichern, und gib dann das Ergebnis aus

// TODO: Verwende storeData(), um Daten mit Datenbankspeicher zu speichern, und gib dann das Ergebnis aus

// TODO: Use fetchData() to retrieve from file storage, then print the result
?>
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Online-PHP-Compiler