Für das falsch geschriebene vehement könnte ich dich kritisieren, aber für die fachliche Diskussion brauche ich dieses Adjektiv nicht.
Danke für den Hinweis, ist korrigiert.
Die Propertys mit Typ auszuzeichnen ergab (in PHP 7.2) einen Fehler. Das hab ich auch im Handbuch so nicht gefunden.
Du hast recht, das ist erst für 7.4 vorgesehen. Mein Code-Editor ist mir da schon in der Zeit voraus.
Hier mal meine Variante:
[…]
Weniger Tipparbeit und man muss nicht unterscheiden, ob man$x->getFoo()
oder$x->foo
schreiben muss. Man kann noch mehr Fehlerbehandlung in __get() einbauen, aber die hauseigenen PHP-Meldungen reichen im Prinzip aus, um unzulässige Zugriffe zu erkennen. Ein __set(), das eine Exception wirft, wäre vielleicht noch sinnvoll, denn ohne dies kann man beliebige Eigenschaften hinzufügen, die andere Namen haben als den privaten Eigenschaften.Mit dem Magic Getter geht leider der Type Hint für den Variablentyp verloren […]
Und damit auch ein paar Intellisense-Funktionen und Autovervollständigung. Deshalb hab ich mich für die ausgeschriebene Variante entschieden. Früher habe ich aber auch regelmäßig die magic-Methods benutzt, um mir die Tipparbeit zu sparen. Inzwischen nehme ich bei solchen No-Brainern die Tipparbeit aber häufiger in Kauf, auch wenn das nur marginale Vorteile mit sich bringt.
aber ich glaube mich zu erinnern, dass es da PHPDoc-Syntax gibt, um solche versteckten Eigenschaften der IDE bekanntzugeben.
Ah, das kannte ich noch gar nicht. Habs aber für alle Interessierten in den Docs gefunden: @property. Falls sich für mich nochmal eine Gelegenheit ergibt, werde ich das mal ausprobieren.
Eine andere Design-Entscheidung von mir ist die Klasse mit
final
auszuzeichnen. Das ist in diesem Fall auch rein meinen persönliche Vorlieben geschuldet: ich bevorzuge Komposition gegenüber Vererbung, deshalb öffne ich meine Klassen nur für Vererbung, wenn ich sie wirklich mal brauche.Selbst wenn ich sie als final ansehe, würde ich dieses Schlüsselwort nicht setzen wollen. Was stört es mich denn, wenn ein Verwender davon erbt, wenn das unbedingt gewünscht ist? Aus welchem Grunde muss ich das aktiv verhindern?
Zum einen schütze ich die Nutzer und Nutzerinnen der Klasse vor einer Verwendung, die ich als Autor nicht beabsichtigt habe und die auf seiner bzw. ihrer Seite früher oder später für Frustration sorgen wird: Methodenüberladung kann dafür sorgen, dass Implementierungs-Details der Elternklasse die Kindklasse auf unvorhersehbare Weise beeinflussen. Gehen wir zum Beispiel von einer Klasse A
mit zwei öffentlichen Methoden aus:
class A
{
public function foo()
{
// Some Code
}
public function bar()
{
// Some Other Code
}
}
Ein kleiner Test zwischendurch:
$a = new A()
$a->foo(); // 42
Klasse B
erbt von A
und überschreibt die Methode bar
:
class B extends A
{
public function bar()
{
throw new Exception("Some men just want to watch the world burn.");
}
}
Frage, zu welchem Wert evaluiert die zweite Zeile in folgendem Code?
$b = new B();
$b->foo(); // ???
Ich rate ein paar Augeblicke darüber nachzudenken bevor man weiterliest. Ein kleiner Tipp: Die Antwort steckt nicht allein im Code.
Egal, wie die Antwortet lautet, sie gehört vermutlich zu den richtigen Lösungsmöglichkeiten. Es kommt nämlich darauf an, wie foo
in Klasse A
implementiert ist, wenn foo
direkt 42
zurückgibt, ist die Antwort auch dieses mal 42
. Wenn A
aber intern $this->bar()
aufruft, dann führt das zu einer Exception.
Der Knackpunkt ist, dass man als Autor der Klasse B nicht wissen kann, wie sie sich verhalten wird, wenn nur eine einzige Methode überschrieben wird, außer man sieht sich die Implementierung der Elternklasse an.
Zum aderen sorge ich mit final
auch dafür, dass die Schnittstelle homogen genutzt wird, ich gebe dem Verwender eine klare Intention zu ihrem Gebrauch mit. Das macht es einfacher für verschiedene Nutzer Code miteinander zu teilen. Ich habe vor Jahren mal irgendwas mit FPDF machen müssen – eine PDF-Library für PHP – die damals noch aus einer Gottklasse bestand. Ich brauchte zwei Zusatzfunktionen, die nicht in FDPF enthalten waren, aber es gab entsprechende Erweiterungsmodule dafür. Das Problem war, dass beide Module jeweils von FPDF geerbt haben und obwohl die Features völlig orthogonal zueinander waren, konnte ich sie nicht zusammen benutzen, einfach weil die AutorInnen sich damals für Vererbung als Mittel der Wahl entschieden haben. Damals habe ich das Problem gelöst, indem ich mir den Code der Erweiterungen kopiert und so modifiziert habe, dass sie kompositionell zusammenarbeiteten, das war ein Aha-Moment für mich.