Ich frage mich, warum PHP Trait (PHP 5.4) keine Schnittstellen implementieren kann.
Für ein Update von der Antwort von user1460043 => ... kann keine Klasse erforderlich sein, die es zum Implementieren einer bestimmten Schnittstelle verwendet
Ich verstehe, dass es offensichtlich sein könnte, weil die Leute denken könnten, wenn a Class A
ein verwendet, Trait T
das ein implementiert interface I
, dann Class A
sollte das das interface I
ungerichtete implementieren (und dies ist nicht wahr, weil Class A
es Merkmalsmethoden umbenennen könnte).
In meinem Fall ruft mein Merkmal Methoden von der Schnittstelle auf, die die Klasse, die das Merkmal verwendet, implementiert.
Das Merkmal ist in der Tat eine Implementierung einiger Methoden der Schnittstelle. Also möchte ich im Code "entwerfen", dass jede Klasse, die mein Merkmal verwenden möchte, die Schnittstelle implementieren muss. Dies würde es dem Merkmal ermöglichen, von der Schnittstelle definierte Klassenmethoden zu verwenden und sicherzustellen, dass sie in der Klasse vorhanden sind.
Antworten:
Die wirklich kurze Version ist einfacher, weil Sie nicht können. So funktionieren Eigenschaften nicht.
Wenn Sie
use SomeTrait;
in PHP schreiben , weisen Sie den Compiler (effektiv) an, den Code aus dem Merkmal zu kopieren und in die Klasse einzufügen, in der er verwendet wird.Da sich das
use SomeTrait;
innerhalb der Klasse befindet, kann es nichtimplements SomeInterface
zur Klasse hinzugefügt werden , da dies außerhalb der Klasse liegen muss.Weil sie nicht instanziiert werden können. Merkmale sind eigentlich nur ein Sprachkonstrukt (das den Compiler anweist, den Merkmalcode zu kopieren und in diese Klasse einzufügen), im Gegensatz zu einem Objekt oder Typ, auf das Ihr Code verweisen kann.
Dies kann erzwungen werden, indem eine abstrakte Klasse für
use
das Merkmal verwendet und dann Klassen daraus erweitert werden.Wenn Sie jedoch durchsetzen müssen, dass eine Klasse, die ein Merkmal verwendet, eine bestimmte Methode hat, verwenden Sie möglicherweise Merkmale, bei denen Sie eigentlich abstrakte Klassen sein sollten.
Oder dass Sie Ihre Logik falsch herum haben. Sie sollten Klassen benötigen, die Schnittstellen implementieren, die bestimmte Funktionen haben, und nicht, dass sie sich selbst als Implementierung einer Schnittstelle deklarieren müssen, wenn sie bestimmte Funktionen haben.
Bearbeiten
Tatsächlich können Sie abstrakte Funktionen in Traits definieren, um eine Klasse zur Implementierung der Methode zu zwingen. z.B
Dies erlaubt Ihnen jedoch immer noch nicht, die Schnittstelle in das Merkmal zu implementieren, und riecht immer noch nach einem schlechten Design, da Schnittstellen viel besser sind als Merkmale bei der Definition eines Vertrags, den eine Klasse erfüllen muss.
quelle
type
Methode ). Können Sie sich vorstellen, wie dies ohne Merkmale umgesetzt werden könnte?Es gibt einen RFC: Merkmale mit Schnittstellen schlagen vor, der Sprache Folgendes hinzuzufügen:
Für die Schnittstelle erforderliche Methoden können entweder vom Merkmal implementiert oder als abstrakt deklariert werden. In diesem Fall wird erwartet, dass die Klasse, die das Merkmal verwendet, es implementiert.
Diese Funktion wird derzeit von der Sprache nicht unterstützt, wird jedoch derzeit geprüft (aktueller Status des RFC lautet: Unter Diskussion ).
quelle
Das klingt sehr vernünftig und ich würde nicht sagen, dass irgendetwas mit Ihrem Design nicht stimmt. Mit dieser Idee wurden Merkmale vorgeschlagen, siehe den zweiten Punkt hier:
Schärli et al., Traits: Composable Units of Behavior, ECOOP'2003, LNCS 2743, S. 248–274, Springer Verlag, 2003, Seite 2
Daher wäre es vielleicht angemessener zu sagen, dass für ein Merkmal eine Schnittstelle erforderlich sein soll , und nicht, um es zu "implementieren".
Ich sehe keinen Grund, warum es unmöglich sein sollte, diese Funktion "Merkmal erfordert (seine Verbraucherklassen müssen implementiert werden) eine Schnittstelle" in PHP zu haben, aber derzeit scheint es zu fehlen.
Wie @Danack in seiner Antwort feststellt , können Sie abstrakte Funktionen im Merkmal verwenden, um sie von Klassen zu "fordern", die das Merkmal verwenden. Leider können Sie dies nicht mit privaten Funktionen tun .
quelle
Ich stimme der Antwort von @Danack zu, werde sie jedoch ein wenig ergänzen.
Ich kann mir nur wenige Fälle vorstellen, in denen das, was Sie anfordern, notwendig ist und als Designproblem offensichtlicher ist als als Sprachfehler. Stellen Sie sich vor, es gibt eine Schnittstelle wie diese:
Es wurde ein Merkmal erstellt, das eine der in der Schnittstelle definierten Funktionen implementiert, dabei jedoch andere Funktionen verwendet, die ebenfalls von der Schnittstelle definiert werden . Dies führt zu dem Fehler, dass, wenn die Klasse, die das Feature verwendet, die Schnittstelle nicht implementiert , alles nicht abgerufen werden kann auslösen
Eine einfache Lösung besteht darin, die Klasse, die das Merkmal verwendet, zu zwingen, auch diese Funktionen zu implementieren:
Das Merkmal ist also nicht vollständig von der Schnittstelle abhängig , sondern ein Vorschlag zur Implementierung einer seiner Funktionen, da die Klasse bei Verwendung des Merkmals die Implementierung der abstrakten Methoden verlangt.
Endgültiges Design
Bitte entschuldigen Sie mein Englisch
quelle