Skip to content

6. Schnittstellen

Eine Schnittstelle ist eine Struktur, die Methodenprototypen definiert. Eine Klasse, die eine Schnittstelle implementiert, muss den Code für alle Methoden der Schnittstelle definieren.

6.1. Der Skriptbaum

Image

6.2. Eine erste Schnittstelle

Wir definieren eine Schnittstelle [IExample] in einem Skript [IExample.php]. Im selben Skript definieren wir zwei Klassen, die die Schnittstelle [IExample] implementieren:


<?php
 
// strict adherence to function parameter types
declare(strict_types=1);
 
// namespace
namespace Exemples;
 
// an interface
interface IExemple {
    // interface methods
    public function ajouter(int $i, int $j): int;
    public function soustraire(int $i, int $j): int;
}
 
// implementation 1 of the IExemple interface
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;
    }
 
}
 
// implementation 2 of the IExemple interface
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 „IExample“ definiert zwei Methoden: die Funktion „add“ (Zeile 12) und die Funktion „subtract“ (Zeile 13). Die Schnittstelle definiert keinen Code für diese Methoden. Dies übernehmen die Klassen, die die Schnittstelle implementieren;
  • Zeile 17: Die Klasse „Class1“ implementiert die Schnittstelle „IExample“. Sie definiert daher den Code für die Methode „add“ (Zeile 18) und die Methode „subtract“ (Zeile 22);
  • Zeilen 29–38: dasselbe gilt für die Klasse Class2;

Wir verwenden die Schnittstelle [IExample] im folgenden Skript [interfaces-01.php]:


<?php
 
require_once "IExemple.php";
use \Exemples\Classe1;
use \Exemples\Classe2;
use \Exemples\IExemple;
 
// function
function calculer(int $a, int $b, IExemple $interface) : void {
  print $interface->ajouter($a, $b)."\n";
  print $interface->soustraire($a, $b)."\n";
}
 
// ------------------- hand
// creation of 2 objects of type Class1 and Class2
$c1 = new Classe1();
$c2 = new Classe2();
// call the calculate function
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 include-Anweisung haben wir hier die require_once-Anweisung verwendet. Die include-Anweisung bindet eine Datei in das aktuelle Skript ein, auch wenn sie bereits eingebunden wurde, während die require_once-Anweisung sie nur einmal einbindet. Daher bevorzugen wir beim Einbinden von Code die require_once-Anweisung;
  • Zeilen 9–12: Wir definieren eine Funktion;
  • Zeile 9: Hier deklarieren wir die Typen der drei Parameter. Wenn der tatsächliche Parameter zur Laufzeit nicht vom erwarteten Typ ist, wird ein Fehler ausgelöst. Der dritte Parameter ist vom Typ [IExample]. Das bedeutet, dass der tatsächliche Parameter eine Instanz einer Klasse sein muss, die die Schnittstelle [IExample] implementiert; in unserem Beispiel bedeutet dies eine Instanz der Klassen [Class1] oder [Class2];
  • Zeilen 10–11: Wir verwenden die Methoden [add, subtract] der Schnittstelle [IExample];
  • Zeile 19: Der dritte tatsächliche Parameter ist vom Typ [Class1], der mit dem Typ [IExample] des dritten formalen Parameters der Funktion kompatibel ist;
  • Zeile 20: Gleiches gilt für die Klasse [Class2];

Ergebnisse

1
2
3
4
17
21
127
201

6.3. Eine Schnittstelle ableiten

Genauso wie eine untergeordnete Klasse eine übergeordnete Klasse erweitern kann, kann eine untergeordnete Schnittstelle eine übergeordnete Schnittstelle erweitern.

Betrachten Sie die Schnittstelle [IExample2], die in der Datei [IExample2.php] definiert ist:


<?php
 
// strict adherence to function parameter types
declare(strict_types=1);
// namespace
namespace Exemples;
 
// interface definition IExemple included
require_once __DIR__."/IExemple.php";
 
// an interface derived from IExemple
interface IExemple2 extends IExemple {
    // the interface method
    public function multiplier(int $i, int $j): int;
}
 
// implementation of IExemple2 interface
class Classe3 extends Classe2 implements IExemple2 {
   
    public function multiplier(int $a, int $b): int {
        return $a * $b;
    }
 
}

Kommentare

  • Zeile 6: Die Schnittstelle [IExample2] befindet sich im selben Namespace wie die Schnittstelle [Iexample];
  • Zeile 9: Die Definitionsdatei für die Schnittstelle [Iexample] wird eingebunden;
  • Zeilen 12–15: Definieren die Schnittstelle [IExample2], die die Schnittstelle [IExample] erweitert (von ihr erbt) und ihr eine neue Methode hinzufügt (Zeile 14);
  • Zeilen 18–24: Die Klasse [Class3] erweitert die Klasse [Class2]. Da [Class2] die Schnittstelle [IExample] implementiert, wird [Class3] diese ebenfalls implementieren. Tatsächlich erbt [Class3] alle öffentlichen und geschützten Methoden der Klasse [Class2], einschließlich der Methoden add und subtract. Darüber hinaus legen wir fest, dass [Class3] die Schnittstelle [IExample2] implementiert. Daher muss sie auch die Methode multiply implementieren, was bei [Class2] nicht der Fall ist. Dies wird in den Zeilen 20–22 umgesetzt;

Die Schnittstelle [IExample2] wird vom folgenden Skript [interfaces-02] verwendet:


<?php
 
// strict adherence to function parameter types
declare(strict_types=1);
 
// inclusion and qualification of classes and interfaces required by the script
require_once __DIR__."/Iexemple2.php";
use \Exemples\IExemple2;
use \Exemples\Classe3;
 
// function
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";
}
 
// ------------------- hand
// creation of 1 Class3 object implementing IExemple2
$c3 = new Classe3();
// call the calculate function
calculer(4, 3, $c3);

Kommentare

  • Zeile 12: Der dritte Parameter der Funktion [calculate] ist vom Typ [IExample2];
  • Zeilen 13–15: Die drei Methoden der Schnittstelle [IExample2] werden verwendet;
  • Zeile 22: Die Funktion [calculate] wird mit einem Objekt vom Typ [IExample2] als drittem Parameter aufgerufen (Zeile 20);

Ergebnisse

1
2
3
107
201
12

6.4. Übergabe einer Schnittstelle als Funktionsparameter

Im vorherigen Abschnitt haben wir 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 im folgenden Skript [interfaces-03.php] gezeigt:


<?php
 
// strict adherence to function parameter types
declare(strict_types=1);
 
// inclusion and qualification of classes and interfaces required by the script
require_once __DIR__."/IExemple.php";
use \Exemples\IExemple;
require_once __DIR__."/IExemple2.php";
use \Exemples\Classe3;
 
// function
function calculer(int $a, int $b, IExemple $interface) {
  print $interface->ajouter($a, $b) . "\n";
  print $interface->soustraire($a, $b) . "\n";
}
 
// ------------------- hand
// creation of 1 object of type Class3 which implements IExemple2 and therefore IExemple
$c3 = new Classe3();
// call the calculate function
calculer(4, 3, $c3);

Kommentare

  • Zeile 13: Die Funktion [calculate] erwartet als dritten Parameter einen Typ [IExample]. Das bedeutet, dass der tatsächliche Parametertyp entweder [IExample] oder ein abgeleiteter Typ sein kann;
  • Zeile 20: Wir instanziieren ein Objekt $c3 vom Typ [Class3], eine Klasse, die die Schnittstelle [IExample2] implementiert, die ihrerseits die Schnittstelle [IExample] erweitert. Letztendlich implementiert $c3 also die Schnittstelle [IExample];
  • Zeile 22: Wir rufen die Funktion [calculate] mit einem Objekt $c3 vom Typ [Class3] als dritten Parameter auf. Durch das Zusammenspiel von Klassenvererbung und Implementierungen haben wir gesehen, dass das Objekt $c3 den Typ [IExample] implementiert. Wir können es daher als dritten Parameter verwenden;

Ergebnisse

107
201