Moin!
Als es noch keine Interfaces in PHP gab, musste man sich so behelfen. Da PHP das nicht mehr tun muss, funktioniert es also nicht.
PHP 4 hat nahezu keine interessanten OOP-Features implementiert gehabt, lediglich simple Vererbung. Ich glaube kaum, dass man in diesem mangelhaften Zustand Interfaces simulieren wollte - man kann ja nur von genau einer Klasse erben, man kann aber parallel mehr als ein Interface implementieren.
Ich denke aber auch, dass es nicht sinnvoll ist, sich über diese alte PHP-Version noch Gedanken zu machen.
Ja aber in dem Fall handelt es sich ja nicht um ein Interface. Fragt PHP also intern ab ob eine Exception tatsächlich von der Exception-Klasse erbt anstatt nur die Signatur der Klasse zu überprüfen? Oder halt im Falle eines Interface, wird auf das Interface geprüft und nicht auf die vorhandenen Funktionen?
Die Exception ist eine Klasse mit diversen finalen Methoden, die man nicht überschreiben kann. Ganz offensichtlich muss eine werfbare Exception die Prüfung $exception instanceof \Exception
bestehen.
Ich gebe auch gerne zu, dass ich den Sinn hinter Interfaces nie verstanden habe. Für mich ist das einfach nur doppelter Code. Oder ich habe es nie gebraucht und kann den Nutzen deshalb nicht so ganz nachvollziehen...
Interfaces sind Vereinbarungen über die Existenz von Methoden.
Wenn du dir mal ein sehr einfaches Interface ansiehst:
interface \Countable {
public function count();
}
Das ist funktionsmäßig nicht der Wahnsinn, aber der Zweck (ohne Beachtung der PHP-internen Magie) ist recht simpel:
Wenn du als Typehint in einer Funktion forderst, dass ein Parameter vom Typ "Countable" ist, dann kannst du dieser Funktion nur Objekte übergeben, die dieses Interface implementieren. Innerhalb dieser Funktion ist dann garantiert, dass du bei dem Objekt die Methode "count" aufrufen kannst. Nicht garantiert ist, welche anderen Methoden du an dem Objekt noch aufrufen kannst. PHP prüft an dieser Stelle den Typehint nicht und verhindert Aufrufe typfremder Methoden nicht (anders als Java).
Als Codebeispiel:
public function addiereAnzahl(Countable $objekt) {
$this->summe = $this->summe + $objekt->count();
return $this->summe;
}
PHP hat für dieses Interface eigene Magie eingeführt: Wenn man count($objekt)
aufruft, und das Objekt das Countable-Interface implementiert, wird die count-Funktion aufgerufen und die zurückgegebene Zahl als Funktionsergebnis von count() zurückgegeben. Ein Objekt, welches nicht Countable implementiert, gibt beim Funktionsaufruf immer 1 zurück.
Obwohl es hier um die etwas merkwürdige Überlappung von Objektorientierung mit prozeduraler Programmierung geht (count ist ja "nur" eine normale Funktion), demonstriert es ein wichtiges Feature von Interfaces: WENN das Interface implementiert wurde, dann MÜSSEN alle Interface-Funktionen existieren, und dann kann man sie auch jederzeit aufrufen. Bei der Funktion "count" wird das dynamisch erkannt, bei dem Beispiel oben MUSS man es tun.
Nun ist es irrelevant, irgendwelche Interfaces zu implementieren, wenn man sowieso nur genau eine Klasse von irgendwas hat. Spannend wird's aber, wenn man verschiedene Klassen hat, die alle so ungefähr dasselbe tun, aber in den Details eben doch unterschiedlich.
Das Countable-Interface ist beispielsweise geschaffen worden, um Objekte so behandeln zu können, wie Arrays (der wichtigere Rest steckt im ArrayAccess-Interface). Objekte machen die unterschiedlichsten Dinge, aber weil man eventuell eine Reihe von Objekten hat, die eine Liste oder ein Array von weiteren Objekten enthalten, und man deren Anzahl erfahren will, ist dieses Interface prima: Wie man die Anzahl zu ermitteln hat, ist stark vom eigentlichen Objekt abhängig, aber die Details interessieren die Außenwelt nicht - die will nur wissen, wie sie an die Anzahl kommt. Und anstatt jetzt pro Objekt irgendeine beliebig benannte Funktion zu erfinden, kann man eben einfach auch Countable implementieren, das für genau diese Aufgabe geschaffen wurde.
Und wenn ein Typehint lediglich "Countable" fordert, sagt er: Mir egal, was das Objekt sonst noch an Methoden kann, ich bin ausschließlich daran interessiert, dass ich die Methode "count" am Objekt aufrufen kann und eine Anzahl bekomme.
- Sven Rautenberg