6. Schnittstellen
Eine Schnittstelle ist eine Struktur, die Methodenprototypen definiert. Eine Klasse, die eine Schnittstelle implementiert, muss den Code aller Methoden der Schnittstelle definieren.
6.1. Die Skript-Baumstruktur

6.2. Eine erste Schnittstelle
Wir definieren eine Schnittstelle [IExemple] in einem Skript [IExemple.php]. Im selben Skript definieren wir zwei Klassen, die die Schnittstelle [IExemple] implementieren:
<?php
// Strikte Einhaltung der Typen der Funktionsparameter
declare(strict_types=1);
// Namensraum
namespace Exemples;
// eine Schnittstelle
interface IExemple {
// Methoden der Schnittstelle
public function ajouter(int $i, int $j): int;
public function soustraire(int $i, int $j): int;
}
// Implementierung 1 der Schnittstelle IExemple
class Classe1 implements IExemple {
public function ajouter(int $a, int $b): int {
return $a + $b + 10;
}
public function soustraire(int $a, int $b): int {
return $a - $b + 20;
}
}
// Implementierung 2 der Schnittstelle IExemple
class Classe2 implements IExemple {
public function ajouter(int $a, int $b) : int{
return $a + $b + 100;
}
public function soustraire(int $a, int $b) : int {
return $a - $b + 200;
}
}
Kommentare
- Zeilen 10–14: Die Schnittstelle IExemple definiert zwei Methoden: die Funktion ajouter (Zeile 12) und die Funktion soustraire (Zeile 13). Die Schnittstelle definiert den Code dieser Methoden nicht. Dies übernehmen die Klassen, die die Schnittstelle implementieren;
- Zeile 17: Die Klasse Classe1 implementiert die Schnittstelle IExemple. Sie definiert daher einen Code für die Methoden ajouter (Zeile 18) und soustraire (Zeile 22);
- Zeilen 29–38: dasselbe gilt für die Klasse „Classe2“;
Wir verwenden die Schnittstelle [IExemple] im folgenden Skript [interfaces-01.php]:
<?php
require_once "IExemple.php";
use \Exemples\Classe1;
use \Exemples\Classe2;
use \Exemples\IExemple;
// Funktion
function calculer(int $a, int $b, IExemple $interface) : void {
print $interface->ajouter($a, $b)."\n";
print $interface->soustraire($a, $b)."\n";
}
// ------------------- main
// Erstellung von 2 Objekten vom Typ Klasse1 und Klasse2
$c1 = new Classe1();
$c2 = new Classe2();
// Aufruf der Funktion „berechnen“
calculer(4, 3, $c1);
calculer(14, 13, $c2);
Kommentare
- Zeilen 3–6: Einbindung und Definition der vom Skript verwendeten Klassen und Schnittstellen;
- Zeile 3: Anstelle der Anweisung „include“ haben wir hier die Anweisung „require_once“ verwendet. Die Anweisung „include“ bindet eine Datei in das aktuelle Skript ein, auch wenn diese bereits eingebunden wurde, während die Anweisung require_once sie nur einmal einbindet. Was die Einbindung von Code betrifft, ist daher die Anweisung require_once vorzuziehen;
- Zeilen 9–12: Hier wird eine Funktion definiert;
- Zeile 9: Hier haben wir den Typ der drei Parameter deklariert. Wenn der tatsächliche Parameter bei der Ausführung nicht dem erwarteten Typ entspricht, wird ein Fehler ausgelöst. Der dritte Parameter ist vom Typ [IExemple]. Das bedeutet, dass der tatsächliche Parameter eine Instanz einer Klasse sein muss, die die Schnittstelle [IExemple] implementiert, also in unserem Beispiel eine Instanz der Klassen [Classe1] oder [Classe2];
- Zeilen 10–11: Wir verwenden die Methoden [ajouter, soustraire] der Schnittstelle [IExemple];
- Zeile 19: Der dritte effektive Parameter ist vom Typ [Classe1] und mit dem Typ [IExemple] des dritten formalen Parameters der Funktion kompatibel;
- Zeile 20: dasselbe gilt für die Klasse [Classe2];
Ergebnisse
6.3. Ableitung einer Schnittstelle
Genauso wie eine untergeordnete Klasse eine übergeordnete Klasse erweitern kann, kann eine untergeordnete Schnittstelle eine übergeordnete Schnittstelle erweitern.
Betrachten wir die Schnittstelle [IExemple2], die in der Datei [IExemple2.php] definiert ist:
<?php
// Strikte Einhaltung der Typen der Funktionsparameter
declare(strict_types=1);
// Namensraum
namespace Exemples;
// Einbindung der Definition der Schnittstelle IExemple
require_once __DIR__."/IExemple.php";
// eine Schnittstelle, die von IExemple abgeleitet ist
interface IExemple2 extends IExemple {
// die Methode der Schnittstelle
public function multiplier(int $i, int $j): int;
}
// Implementierung der Schnittstelle IExemple2
class Classe3 extends Classe2 implements IExemple2 {
public function multiplier(int $a, int $b): int {
return $a * $b;
}
}
Anmerkungen
- Zeile 6: Die Schnittstelle [IExemple2] befindet sich im selben Namensraum wie die Schnittstelle [Iexemple];
- Zeile 9: Die Definitionsdatei der Schnittstelle [Iexemple] wird eingebunden;
- Zeilen 12–15: Definieren die Schnittstelle [IExemple2], die die Schnittstelle [Iexemple] erweitert (erbt) und ihr eine neue Methode hinzufügt (Zeile 14);
- Zeilen 18–24: Die Klasse [Classe3] erweitert die Klasse [Classe2]. Da diese die Schnittstelle [IExemple] implementiert, gilt dies auch für die Klasse [Classe3]. Tatsächlich erbt [Classe3] alle öffentlichen und geschützten Methoden der Klasse [Classe2], also die Methoden „addieren“ und „subtrahieren“. Außerdem wird angegeben, dass [Classe3] die Schnittstelle [IExemple2] implementiert. In dieser Eigenschaft muss sie auch die Methode „multiplier“ implementieren, was bei [Classe2] nicht der Fall ist. Dies geschieht in den Zeilen 20–22;
Die Schnittstelle [IExemple2] wird vom folgenden Skript [interfaces-02] genutzt:
<?php
// Strikte Einhaltung der Parametertypen der Funktionen
declare(strict_types=1);
// Einbindung und Qualifizierung der für das Skript erforderlichen Klassen und Schnittstellen
require_once __DIR__."/Iexemple2.php";
use \Exemples\IExemple2;
use \Exemples\Classe3;
// Funktion
function calculer(int $a, int $b, IExemple2 $interface) {
print $interface->ajouter($a, $b) . "\n";
print $interface->soustraire($a, $b) . "\n";
print $interface->multiplier($a, $b) . "\n";
}
// ------------------- main
// Erstellung eines Objekts vom Typ „Classe3“, das IExemple2 implementiert
$c3 = new Classe3();
// Aufruf der Funktion „berechnen“
calculer(4, 3, $c3);
Kommentare
- Zeile 12: Der dritte Parameter der Funktion [calculer] ist vom Typ [IExemple2];
- Zeilen 13–15: Es werden die drei Methoden der Schnittstelle [IExemple2] verwendet;
- Zeile 22: Die Funktion [calculer] wird mit einem Objekt vom Typ [IExemple2] (Zeile 20) als drittem Parameter aufgerufen;
Ergebnisse
6.4. Übergabe einer Schnittstelle als Funktionsparameter
Wir haben im vorigen Abschnitt gesehen, dass, wenn der erwartete Typ für einen Funktionsparameter eine Klasse ist, der tatsächliche Parameter ein Objekt des erwarteten Typs oder eines abgeleiteten Typs sein kann. Dasselbe gilt für Schnittstellen, wie das folgende Skript [interfaces-03.php] zeigt:
<?php
// Strikte Einhaltung der Typen der Funktionsparameter
declare(strict_types=1);
// Einbindung und Qualifizierung der für das Skript erforderlichen Klassen und Schnittstellen
require_once __DIR__."/IExemple.php";
use \Exemples\IExemple;
require_once __DIR__."/IExemple2.php";
use \Exemples\Classe3;
// Funktion
function calculer(int $a, int $b, IExemple $interface) {
print $interface->ajouter($a, $b) . "\n";
print $interface->soustraire($a, $b) . "\n";
}
// ------------------- main
// Erstellung eines Objekts vom Typ „Classe3“, das IExemple2 und damit IExemple implementiert
$c3 = new Classe3();
// Aufruf der Funktion „berechnen“
calculer(4, 3, $c3);
Kommentare
- Zeile 13: Die Funktion [calculer] erwartet als dritten Parameter einen Typ [IExemple]. Das bedeutet, dass der Typ des tatsächlichen Parameters vom Typ [IExemple] oder davon abgeleitet sein kann;
- Zeile 20: Es wird ein Objekt vom Typ $c3 instanziiert, das vom Typ [Classe3] ist – eine Klasse, die die Schnittstelle [IExemple2] implementiert, welche wiederum die Schnittstelle [IExemple] erweitert. Letztendlich implementiert also $c3 die Schnittstelle [IExemple];
- Zeile 22: Die Funktion [calculer] wird aufgerufen, wobei als dritter Parameter ein Objekt $c3 vom Typ [Classe3] übergeben wird. Durch Klassenvererbung und Implementierungen haben wir gesehen, dass das Objekt $c3 den Typ [IExemple] implementiert. Es kann daher als dritter Parameter verwendet werden;
Ergebnisse