Hallo!
echo $begrüßung;
Es gibt eine Superklasse SK.
Welche Aufgabe hat diese?
Dort sind einige wichtige Eigenschaften und Methoden definiert, die für alle UKs gleich sind.
Es gibt einige Klassen, die von SK ableiten: UK1, UK2 usw.
Und wozu dienen diese? Hast du mehrere Plugin-Stellen in deinem Programm und jeweils eine UK ist für solch eine Stelle zuständig? Und SK ist eine generische Klasse solch einer Plugin-Stelle?
Die UKs sind im Prinzip Verfeinerungen von SK.
In SK ist eine statische Methode getPlugins($instance) definiert, die von Instanzen von UK1 usw. aufgerufen wird:
$uk1 = new UK1;
In UK1 im Konstruktor:
$this->getPlugins($this);
Mit -> ruft man Methoden dynamisch auf. Statische Aufrufe gehen über klassenname::methodenname(…). Bei $this->getPlugins($this); handelt es sich um einen dynamischen Aufruf und es ist überflüssig, $this zu übergeben, denn innerhalb von getPlugins zeigt $this auf dein $uk1.
Nein, genau das geht leider nicht, weil die statische Methode ja instanzenlos aufgerufen wird. Deswegen kann dort kein Zeiger vorhanden sein.
In SK.getPlugins() findet sowohl der include() als auch die Instanzenbildung
Das sind vermutlich die einzelnen Plugins.
$instance->$newInstance = new $class($instance); statt.
Ich nehme an, in $class befindet sich der Klassenname des Plugins. Spricht was dagegen, die UKx à la PluginPlatz zu benennen und für die Plugin-Klassen die Namenskonvention PluginPlatz_IndividuellerName zu verwenden?
Ja, genau so habe ich es auch gemacht. $newInstance und $class unterscheiden sich nur durch das Präfix für die aufnehmende UK. In $class ist es vorhanden, in $newInstance nicht mehr:
'UK1'->'Plugin1' = new 'UK1_Plugin1'('UK1');
(nur daß statt UK1 Instanzen von UK1 gedacht werden müssen).
Somit kann das Plugin jetzt sehr fein kreiert werden. Wenn es z. B. Funktionalität zu UK1, UK2 und UK7 hinzufügt, gibt es drei Klassen UK1_Plugin4, UK2_Plugin4, UK7_Plugin4. Ärgerlich ist eben der Zwang zu dem Präfix, aber damit muß und kann ich leben.
Es gibt in SK noch eine andere statische Methode, die zuvor eine Liste mit den vorhandenen Plugins erzeugt. Wie zu sehen, reicht getPlugins() mit new $class($instance) den Zeiger weiter, der sodann in dem Plugin gespeichert wird. $newInstance und $class sind im Prinzip nur bereinigte Namen, vgl. das o. g. Problem mit demselbem Namespace.
Auf die Pluginmethoden läßt sich jetzt mit $uk1->plugin->methode() zugreifen. Im Plugin selbst kann auf Methoden von UK1 zugreifen.
Warum muss ein Plugin auf einen Plugin-Handler zugreifen? Um ein Radio zu beschreiben braucht es keinen Verweis auf den Ort an dem es steht. Für unterschiedliche Typen aber eine Klasse anzulegen, die von einer generischen Radioklasse erbt, ist schon eher sinnvoll. So ein Radio braucht zum Arbeiten Instanzen der Klassen Antenne und Lautsprecher. Die sucht es sich aber nicht selbständig aus seiner Umgebung (wofür es einen Verweis auf die Umgebung übergeben benötigte) sondern bekommt sie als Parameter bei der Inbetriebnahme übergeben.
Ok, ich weiß nicht, ob ich Dich richtig verstehe. Man könnte natürlich auch bei Methodenaufrufen der eingeschachtelten Klasse jeweils einen Zeiger auf eine Instanz einer anderen Klasse mit übergeben, damit es dessen Methoden nutzen kann. Das wäre zwar auch eine Möglichkeit, aber ich denke, so wie es jetzt ist, mit einmaliger Übergabe bei Instanzierung ist es für meine Zwecke einfacher.
Schöner wäre es, wenn es nicht nötig wäre, Plugininstanzen mit $instance->$newInstance = new $class($instance); zu bilden, sondern einfach die Pluginklasse als statische Klasse direkt in UK1 einzubinden, um dann von außen mit $uk1->pluginmethode() zugreifen zu können.
Klassen sind während der Laufzeit statische Dinge. Bereits vor dem Kompilieren müssen ihre Beziehungen zueinander feststehen. Auch wenn wie im Falle PHPs Codeteile auch noch zur Laufzeit hinzugefügt werden können, ändert das nichts an ihren feststehenden Beziehungen zueinander.
Wenn jemand ein Plugin schreibt, das auf generische Funktionen zugreifen soll, dann kann man eine Plugin-Elternklasse erstellen, von der dann das Plugin erben kann.
In den UKs sind halt wichtige Methoden und Eigenschaften wie DB-Verbindungen, die für das Plugin vorhanden sein müssen. Es wäre natürlich klasse, wenn man den Zugriff wie bei der Vererbung mittels protected und private steuern könnte. Als anderes Design könnte ich mir noch vorstellen, Dinge, auf die ein Plugin Zugriff haben soll, als weiteres eingeschachteltes Objekt abzubilden und hierauf einen Zeiger zu übergeben, aber das ändert ja nichts an dem architektonischen Konzept.
Das alles ginge natürlich theoretisch, wenn, wie von Dir angeregt, das Plugin selbst von UK erbt. Das Problem ist aber, daß vor Benutzung von Pluginmethoden schon eine Instanz von UK vorhanden ist. Das Plugin müßte deswegen nicht nur die Struktur von UK erben, sondern den konkreten Inhalt von der UK-Instanz. Für alle diese Inhalte nun Schnittstellen nach außen zu erstellen, mittels denen dann das Plugin die Inhalte abrufen kann, mag zwar sauberer, dafür aber auch um ein Vielfaches aufwendiger sein, als wenn einfach eine Nested Class zu einer Instanz von UK hinzugefügt wird.
Klassen so zu designen, dass sie viele Dinge von ihrer Umgebung wissen müssen, nach denen sie noch dazu selbständig greifen sollen, ist kein gutes Design. Alles was sie wissen müssen, sollte man ihnen übergeben. Man kann sie besser testen (händisch als auch mit Unit-Tests), wenn man nicht erst eine komplexe Umgebung aufbauen muss. Besser ist es, das Benötigte in Form von Dummys zu übergeben.
Siehe oben.