implements
Lernen Sie, wie PHPs "implements" Interface-Verträge durchsetzt. Syntax, mehrere Interfaces, Konstanten, Type Hinting und häufige Fehler.
Das PHP implements-Schlüsselwort
Das Schlüsselwort implements teilt PHP mit, dass eine Klasse den Vertrag erfüllen wird, der durch ein Interface definiert ist. Ein Interface listet Methodensignaturen (und optional Konstanten) auf, aber keine Methodenrümpfe; eine Klasse, die es implementiert, muss für jede vom Interface deklarierte Methode einen konkreten Rumpf bereitstellen. Falls nicht, wirft PHP einen fatalen Fehler, bevor das Programm ausgeführt wird.
Diese Seite behandelt die Syntax, das gleichzeitige Implementieren mehrerer Interfaces, Interface-Konstanten, Type Hinting gegen Interfaces, häufige Fehler und den Unterschied zwischen implements und extends. Falls Interfaces für Sie neu sind, beginnen Sie mit PHP Interfaces und Was ist OOP.
Syntax
interface MyInterface {
public function doSomething(); // signature only — no body
}
class MyClass implements MyInterface {
public function doSomething() {
// the concrete implementation lives here
}
}MyClass implements MyInterface ist ein Versprechen: „Diese Klasse stellt eine funktionierende Version jeder Methode bereit, die MyInterface erfordert." Das Interface ist das Was; die Klasse ist das Wie.
Ein einfaches Beispiel
<?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!
}Da sowohl Dog als auch Cat das Interface Animal implementieren, kann jeder Code, der ein Animal erwartet, mit beiden arbeiten, ohne die konkrete Klasse zu kennen. Das ist die Grundlage von Polymorphismus in PHP.
Mehrere Interfaces implementieren
Im Gegensatz zu extends (eine Klasse kann nur eine übergeordnete Klasse erweitern) kann eine Klasse beliebig viele Interfaces implementieren — trennen Sie sie durch Kommas. Die Klasse muss alle Methoden aus jedem aufgelisteten Interface erfüllen.
<?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 lowSo erhält PHP die Vorteile der Mehrfachvererbung (mehrere Verträge teilen), ohne deren Nachteile (mehrdeutige vererbte Implementierungen).
Interface-Konstanten und Type Hinting
Ein Interface kann Konstanten deklarieren, und eine implementierende Klasse greift auf sie wie auf eigene zu. Die eigentliche Stärke liegt jedoch im Type Hinting: Wenn Sie einen Parameter gegen das Interface typisieren, wird jede implementierende Klasse akzeptiert — Sie können Implementierungen daher frei austauschen.
<?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.99Sie können ein Objekt zur Laufzeit auch mit instanceof gegen ein Interface prüfen:
var_dump($gateway instanceof PaymentGateway); // bool(true)Häufige Fehler und Fallstricke
- Eine fehlende Methode ist fatal. Wenn eine Klasse auch nur eine Interface-Methode weglässt, wirft PHP
Fatal error: Class X contains 1 abstract method and must therefore be declared abstract or implement the remaining methods. Die Prüfung erfolgt zur Kompilierzeit, bevor Code ausgeführt wird. - Signaturen müssen kompatibel sein. Ihre Implementierung muss die vom Interface deklarierten Parameter- und Rückgabetypen beibehalten (unter PHPs Varianzregeln dürfen Sie Parametertypen erweitern und Rückgabetypen einschränken, aber Abweichungen sind fatal).
- Interface-Methoden sind implizit
public. Eine Interface-Methode kann nicht alsprotectedoderprivateimplementiert werden. - Interfaces können Interfaces erweitern. Verwenden Sie
interface B extends A, um auf einem anderen Interface aufzubauen; eine Klasse, dieBimplementiert, muss Methoden aus beiden erfüllen. Beachten Sie, dass diesextendsund nichtimplementsverwendet.
implements vs. extends
Diese Schlüsselwörter werden leicht verwechselt:
extends | implements | |
|---|---|---|
| Verwendet mit | einer übergeordneten Klasse (oder Interface→Interface) | einem oder mehreren Interfaces |
| Vererbt Code? | ja — Eigenschaften und Methodenrümpfe | nein — nur den Vertrag (Signaturen) |
| Wie viele? | eine Klasse erweitert eine Klasse | eine Klasse implementiert viele Interfaces |
Eine Klasse kann beides gleichzeitig tun: class Circle extends Shape implements JsonSerializable { ... }. Für Details zur Vererbung siehe PHP extends und, wenn Sie partielle Implementierungen benötigen, abstrakte PHP-Klassen.
Wann sollte man implements verwenden?
Greifen Sie zu einem Interface und implements, wenn:
- Mehrere unverwandte Klassen austauschbar sein müssen (z. B. mehrere Zahlungs-Gateways, Logger oder Cache-Treiber).
- Sie gegen eine Fähigkeit und nicht gegen eine konkrete Klasse typisieren möchten, um den Code lose gekoppelt und mit Mocks leicht testbar zu halten.
- Sie einen öffentlichen API-Vertrag definieren, den andere Klassen — einschließlich solcher, die später oder von anderen Teams geschrieben werden — einhalten müssen.
Wenn Sie stattdessen tatsächlichen Implementierungscode zwischen verwandten Klassen teilen müssen, verwenden Sie Klassenvererbung (extends) oder eine abstrakte Klasse.