Ich suche nach einem guten, sauberen Weg, um die Tatsache zu umgehen, dass PHP5 immer noch keine Mehrfachvererbung unterstützt. Hier ist die Klassenhierarchie:
Nachricht
- TextMessage
-------- InvitationTextMessage
- EmailMessage
-------- InvitationEmailMessage
Die beiden Arten von Einladungsklassen haben viel gemeinsam. Ich würde gerne eine gemeinsame Elternklasse haben, Einladung, von der beide erben würden. Leider haben sie auch viel mit ihren derzeitigen Vorfahren gemeinsam ... TextMessage und EmailMessage. Klassischer Wunsch nach Mehrfachvererbung hier.
Was ist der leichteste Ansatz, um das Problem zu lösen?
Vielen Dank!
php
oop
inheritance
Alex Weinstein
quelle
quelle
Antworten:
Alex, meistens ist eine Mehrfachvererbung ein Signal dafür, dass Ihre Objektstruktur etwas falsch ist. In der von Ihnen skizzierten Situation haben Sie die Klassenverantwortung einfach zu weit gefasst. Wenn die Nachricht Teil des Anwendungsgeschäftsmodells ist, sollte sie sich nicht um das Rendern der Ausgabe kümmern. Stattdessen können Sie die Verantwortung aufteilen und MessageDispatcher verwenden, der die über Text oder HTML-Backend übergebene Nachricht sendet. Ich kenne Ihren Code nicht, aber lassen Sie mich ihn folgendermaßen simulieren:
Auf diese Weise können Sie der Nachrichtenklasse eine Spezialisierung hinzufügen:
Beachten Sie, dass MessageDispatcher je nach
type
Eigenschaft im übergebenen Nachrichtenobjekt eine Entscheidung treffen würde, ob es als HTML oder als einfacher Text gesendet werden soll .Zusammenfassend ist die Verantwortung auf zwei Klassen aufgeteilt. Die Nachrichtenkonfiguration erfolgt in der InvitationHTMLMessage / InvitationTextMessage-Klasse, und der Sendealgorithmus wird an den Dispatcher delegiert. Dies nennt man Strategiemuster, mehr dazu lesen Sie hier .
quelle
Tracing
(dies ist nur ein Beispiel), in der Sie allgemeine Dinge wie das Debuggen in eine Datei, das Senden von SMS für kritische Probleme usw. möchten. Alle Ihre Klassen sind Kinder dieser Klasse. Angenommen, Sie möchten eine Klasse erstellenException
, die diese Funktionen haben soll (= Kind vonTracing
). Diese Klasse muss ein Kind von seinException
. Wie entwirft man solche Sachen ohne Mehrfachvererbung? Ja, Sie haben vielleicht immer eine Lösung, aber Sie werden immer dem Hacken nahe kommen. Und Hacking = auf lange Sicht teure Lösung. Ende der Geschichte.Vielleicht können Sie eine 'is-a'-Beziehung durch eine' has-a'-Beziehung ersetzen? Eine Einladung enthält möglicherweise eine Nachricht, muss jedoch nicht unbedingt eine Nachricht sein. Möglicherweise wird eine Einladung bestätigt, die nicht gut zum Nachrichtenmodell passt.
Suchen Sie nach "Komposition vs. Vererbung", wenn Sie mehr darüber wissen möchten.
quelle
Wenn ich Phil in diesem Thread zitieren kann ...
Und Chris ...
Ich dachte, beide hätten nützliche Links. Ich kann es kaum erwarten, Eigenschaften oder vielleicht ein paar Mixins auszuprobieren ...
quelle
Das Symfony-Framework verfügt über ein Mixin-Plugin , das Sie vielleicht ausprobieren möchten - auch nur für Ideen, wenn Sie es nicht verwenden möchten.
Die Antwort "Entwurfsmuster" besteht darin, die gemeinsam genutzte Funktionalität in eine separate Komponente zu abstrahieren und zur Laufzeit zu komponieren. Überlegen Sie, wie Sie die Einladungsfunktionalität als eine Klasse abstrahieren können, die Ihren Nachrichtenklassen auf andere Weise als durch Vererbung zugeordnet wird.
quelle
Ich verwende Merkmale in PHP 5.4, um dies zu lösen. http://php.net/manual/en/language.oop5.traits.php
Dies ermöglicht eine klassische Vererbung mit Erweiterungen, bietet aber auch die Möglichkeit, gemeinsame Funktionen und Eigenschaften in ein Merkmal zu integrieren. Wie das Handbuch sagt:
quelle
Es hört sich so an, als wäre das Dekorationsmuster geeignet, aber ohne weitere Details schwer zu sagen.
quelle
Dies ist sowohl eine Frage als auch eine Lösung ....
Was ist mit dem magischen _ call (),_get (), __set () Methoden? Ich habe diese Lösung noch nicht getestet, aber was ist, wenn Sie eine MultiInherit-Klasse erstellen? Eine geschützte Variable in einer untergeordneten Klasse kann ein Array von zu erbenden Klassen enthalten. Der Konstruktor in der Multi-Interface-Klasse könnte Instanzen jeder der geerbten Klassen erstellen und sie mit einer privaten Eigenschaft verknüpfen, z. B. _ext. Die Methode __call () kann die Funktion method_exists () für jede der Klassen im Array _ext verwenden, um die richtige aufzurufende Methode zu finden. __get () und __set können verwendet werden, um interne Eigenschaften zu suchen, oder wenn Sie ein Experte mit Referenzen sind, können Sie die Eigenschaften der untergeordneten Klasse und der geerbten Klassen als Verweise auf dieselben Daten festlegen. Die Mehrfachvererbung Ihres Objekts wäre für den Code mit diesen Objekten transparent. Ebenfalls, Interne Objekte können bei Bedarf direkt auf die geerbten Objekte zugreifen, solange das Array _ext nach Klassennamen indiziert ist. Ich habe mir vorgestellt, diese Superklasse zu schaffen, und habe sie noch nicht implementiert, da ich der Meinung bin, dass wenn sie funktioniert, dies dazu führen könnte, dass sich unterschiedliche Programmiergewohnheiten entwickeln.
quelle
instanceof
) erbenIch muss ein paar Fragen stellen, um zu klären, was Sie tun:
1) Enthält Ihr Nachrichtenobjekt nur eine Nachricht, z. B. Text, Empfänger, Zeitplan? 2) Was haben Sie mit Ihrem Einladungsobjekt vor? Muss es im Vergleich zu einer EmailMessage speziell behandelt werden? 3) Wenn ja, WAS ist das Besondere daran? 4) Wenn dies der Fall ist, warum müssen die Nachrichtentypen für eine Einladung anders behandelt werden? 5) Was ist, wenn Sie eine Willkommensnachricht oder eine OK-Nachricht senden möchten? Sind sie auch neue Objekte?
Es hört sich so an, als würden Sie versuchen, zu viele Funktionen in einer Reihe von Objekten zu kombinieren, bei denen es nur darum gehen sollte, den Inhalt einer Nachricht zu speichern - und nicht darum, wie damit umgegangen werden soll. Sie sehen, es gibt keinen Unterschied zwischen einer Einladung oder einer Standardnachricht. Wenn die Einladung eine spezielle Behandlung erfordert, bedeutet dies Anwendungslogik und keinen Nachrichtentyp.
Beispiel: Ein von mir erstelltes System hatte ein gemeinsames Basisnachrichtenobjekt, das auf SMS, E-Mail und andere Nachrichtentypen erweitert wurde. Allerdings: Diese wurden nicht weiter erweitert - eine Einladungsnachricht war einfach ein vordefinierter Text, der über eine Nachricht vom Typ E-Mail gesendet werden sollte. Ein bestimmter Einladungsantrag würde sich mit der Validierung und anderen Anforderungen für eine Einladung befassen. Schließlich möchten Sie nur die Nachricht X an den Empfänger Y senden, der ein eigenständiges System sein sollte.
quelle
Gleiches Problem wie Java. Versuchen Sie, Schnittstellen mit abstrakten Funktionen zu verwenden, um dieses Problem zu lösen
quelle
PHP unterstützt Schnittstellen. Dies könnte abhängig von Ihren Anwendungsfällen eine gute Wahl sein.
quelle
Wie wäre es mit einer Einladungsklasse direkt unter der Nachrichtenklasse?
So lautet die Hierarchie:
Nachricht
--- Einladung
------ TextMessage
------ EmailMessage
Fügen Sie in der Einladungsklasse die Funktionen hinzu, die in InvitationTextMessage und InvitationEmailMessage enthalten waren.
Ich weiß, dass Einladung nicht wirklich eine Art von Nachricht ist, sondern eher eine Funktionalität von Nachricht. Ich bin mir also nicht sicher, ob dies ein gutes OO-Design ist oder nicht.
quelle