Kann eine Klasse sowohl eine Klasse erweitern als auch eine Schnittstelle implementieren?

100

Kann eine Klasse sowohl eine Schnittstelle als auch eine andere Klasse in PHP erweitern?
Grundsätzlich möchte ich das machen:

interface databaseInterface{
 public function query($q);
 public function escape($s);
 //more methods
}

class database{ //extends both mysqli and implements databaseInterface
 //etc.
}

Wie würde man das machen, einfach machen:

class database implements databaseInterface extends mysqli{ 

führt zu einem schwerwiegenden Fehler:

Analysefehler: Syntaxfehler, unerwartetes T_EXTENDS, Erwartung '{' in * Datei * in Zeile * Zeile *
Pim Jäger
quelle
18
Wie ist das zu lokalisiert?! "Diese Frage wird zukünftigen Besuchern wahrscheinlich nicht helfen". Die beste Antwort hat jedoch 33 positive Stimmen und die Frage 4 Sterne!
Dualität_

Antworten:

177

Versuchen Sie es anders herum:

class database extends mysqli implements databaseInterface { ...}

Das sollte funktionieren.

Simon Lehmann
quelle
Ahh, vielen Dank. Warum genau sollten sie umgekehrt sein?
Pim Jager
14
Da Sie nur eine Klasse erben und eine beliebige Anzahl von Schnittstellen implementieren können, war dies wahrscheinlich eine Syntaxzuckersache. Denken Sie auch daran, wenn Ihre Unterklasse Schnittstellen implementiert, wird dies auch in der Liste der implementierten Methoden angezeigt. Es macht also Sinn, sie in diese Reihenfolge zu bringen.
Drew
Ist es eine schlechte Praxis?
Mohammed Shamshid
21

Ja, kann es. Sie müssen nur die richtige Reihenfolge beibehalten.

class database extends mysqli implements databaseInterface { ... }

Darüber hinaus kann eine Klasse mehr als eine Schnittstelle implementieren. Trenne sie einfach durch Kommas.

Ich fühle mich jedoch verpflichtet, Sie zu warnen, dass die Erweiterung der MySQL-Klasse eine unglaublich schlechte Idee ist . Vererbung an sich ist wahrscheinlich das am meisten überbewertete und missbrauchte Konzept in der objektorientierten Programmierung.

Stattdessen würde ich empfehlen, db-bezogene Dinge auf mysqli-Weise (oder PDO-Weise) zu tun.

Plus, eine Kleinigkeit, aber Namenskonventionen sind wichtig. Ihre Klasse databasescheint dann allgemeiner zu sein mysqli, daher deutet dies darauf hin, dass letztere von databaseund nicht von der Art und Weise erbt .

Michał Rudnicki
quelle
1
Warum ist die Erweiterung der Mysqli-Klasse eine schlechte Idee?
Pim Jager
11
Erstens, weil es nicht deins ist. Wenn sich Mysqli-Leute dazu entschließen, etwas zu ändern, ändert sich auch das Verhalten einer Unterklasse. Zweitens wird die Vererbung zur SPEZIALISIERUNG verwendet, nicht zur ERWEITERUNG mit zusätzlichen Funktionen. Dies ist die am meisten missverstandene Sache in OOP. Als Faustregel neige ich dazu, nur abstrakte Klassen zu erweitern.
Michał Rudnicki
Michal - wie würde sich eine Änderung an mysqli für einen Entwickler, der einen polymorphen Ansatz verwendet, von einem aggregierten / zusammengesetzten unterscheiden? Sie müssten Ihren Code noch aktualisieren, um die Änderungen zu verarbeiten.
Peter Bailey
2
Ich bin mit dem Adaptermuster vertraut. Ich sage nur, dass Sie in beiden Szenarien den Code ändern müssen, wenn sich ein Methodenname ändert oder veraltet ist. Obwohl ich der Meinung bin, dass ein nicht polymorpher Ansatz in diesem Szenario besser ist, kaufe ich mir nicht die Vorstellung, dass ein Adapter "immun" gegen Änderungen wäre.
Peter Bailey
2
Sie müssen nur den Adaptercode ändern, nicht alle Stellen, die diesen Code verwenden. Mit Komposition können Sie Kompatibilitätsebenen bereitstellen, egal was passiert, während Sie mit Vererbung bestenfalls einen Hack nennen können. Und ich stehe korrigiert da, würde der Adapter eine bessere Immunität gegen Änderungen bieten.
Michał Rudnicki
6

Ja, wenn Sie mehrere Schnittstellen implementieren möchten, können Sie Folgendes tun:

public class MyClass extends BaseClass implements myInterface1, myInterface2, myInterface3{ 

}
Null Zeiger
quelle