Nachdem ich in PHP 5.2 strenge Warnungen aktiviert hatte, sah ich eine Menge strenger Standardwarnungen aus einem Projekt, das ursprünglich ohne strenge Warnungen geschrieben wurde:
Strenge Standards : Statische Funktion Programm :: getSelectSQL () sollte nicht abstrakt sein in Program.class.inc
Die betreffende Funktion gehört zu einem abstrakten übergeordneten Klassenprogramm und wird als abstrakt statisch deklariert, da sie in ihren untergeordneten Klassen wie TVProgram implementiert werden sollte.
Hinweise zu dieser Änderung habe ich hier gefunden :
Abgelegte abstrakte statische Klassenfunktionen wurden gelöscht. Aufgrund eines Versehens erlaubten PHP 5.0.x und 5.1.x abstrakte statische Funktionen in Klassen. Ab PHP 5.2.x können nur Schnittstellen über diese verfügen.
Meine Frage ist: Kann jemand klar erklären, warum es in PHP keine abstrakte statische Funktion geben sollte?
Antworten:
statische Methoden gehören zu der Klasse, die sie deklariert hat. Wenn Sie die Klasse erweitern, können Sie eine statische Methode mit demselben Namen erstellen, aber Sie implementieren tatsächlich keine statische abstrakte Methode.
Gleiches gilt für die Erweiterung einer Klasse mit statischen Methoden. Wenn Sie diese Klasse erweitern und eine statische Methode mit derselben Signatur erstellen, überschreiben Sie die statische Methode der Oberklasse nicht
EDIT (16. September 2009)
Update dazu. Unter PHP 5.3 sehe ich, dass abstrakte statische Daten zurück sind, egal ob gut oder schlecht. ( Weitere Informationen finden Sie unter http://php.net/lsb. )
KORREKTUR (von philfreo)
abstract static
ist in PHP 5.3 immer noch nicht erlaubt, LSB ist verwandt, aber anders.quelle
abstract static
Dies führt zu einer Überlastung der statischen Methode und kann in diesem Fall hilfreich sein.Es ist eine lange, traurige Geschichte.
Als PHP 5.2 diese Warnung zum ersten Mal einführte, waren späte statische Bindungen noch nicht in der Sprache. Falls Sie mit späten statischen Bindungen nicht vertraut sind, beachten Sie, dass Code wie dieser nicht wie erwartet funktioniert:
Abgesehen von der Warnung vor dem strengen Modus funktioniert der obige Code nicht. Der
self::bar()
Aufruf infoo()
bezieht sich explizit auf diebar()
Methode vonParentClass
, auch wennfoo()
er als Methode von aufgerufen wirdChildClass
. Wenn Sie versuchen, diesen Code mit deaktiviertem Strict-Modus auszuführen, wird " Schwerwiegender PHP-Fehler: Abstrakte Methode ParentClass :: bar () kann nicht aufgerufen werden" angezeigt .Vor diesem Hintergrund waren abstrakte statische Methoden in PHP 5.2 nutzlos. Der Sinn einer abstrakten Methode besteht darin, dass Sie Code schreiben können, der die Methode aufruft, ohne zu wissen, welche Implementierung aufgerufen werden soll, und dann verschiedene Implementierungen für verschiedene untergeordnete Klassen bereitstellen können. Da PHP 5.2 keine saubere Möglichkeit bietet, eine Methode einer übergeordneten Klasse zu schreiben, die eine statische Methode der untergeordneten Klasse aufruft, für die sie aufgerufen wird, ist diese Verwendung abstrakter statischer Methoden nicht möglich. Daher ist jede Verwendung
abstract static
in PHP 5.2 ein schlechter Code, wahrscheinlich inspiriert durch ein Missverständnis der Funktionsweise desself
Schlüsselworts. Es war völlig vernünftig, eine Warnung darüber zu werfen.Dann wurde PHP 5.3 hinzugefügt, um auf die Klasse zu verweisen, für die eine Methode über das
static
Schlüsselwort aufgerufen wurde (im Gegensatz zumself
Schlüsselwort, das sich immer auf die Klasse bezieht, in der die Methode definiert wurde ). Wenn Sie ändern ,self::bar()
umstatic::bar()
in meinem Beispiel oben, es funktioniert gut in PHP 5.3 und höher. Sie können mehr überself
vsstatic
bei New self vs. new static lesen .Mit dem hinzugefügten statischen Schlüsselwort war das eindeutige Argument für das
abstract static
Auslösen einer Warnung verschwunden. Der Hauptzweck von späten statischen Bindungen bestand darin, in einer übergeordneten Klasse definierten Methoden das Aufrufen statischer Methoden zu ermöglichen, die in untergeordneten Klassen definiert werden würden. Das Zulassen abstrakter statischer Methoden erscheint angesichts der späten statischen Bindungen vernünftig und konsistent.Sie könnten immer noch dafür eintreten, die Warnung beizubehalten. Zum Beispiel könnte man argumentieren , dass seit PHP können Sie statische Methoden der abstrakten Klassen nennen, in meinem Beispiel oben (auch nachdem sie durch den Austausch Fixierung
self
mitstatic
) Sie aussetzt eine öffentliche Methode ,ParentClass::foo()
die ist gebrochen und dass Sie nicht wirklich wollen entlarven. Die Verwendung einer nicht statischen Klasse - das heißt, alle Methoden zu Instanzmethoden zu machen und die untergeordneten MethodenParentClass
zu Singletons oder Ähnlichem zu machen - würde dieses Problem lösen, daParentClass
sie abstrakt sind und daher nicht instanziiert werden können heißen. Ich denke, dieses Argument ist schwach (weil ich denke, es zu entlarvenParentClass::foo()
ist keine große Sache und die Verwendung von Singletons anstelle von statischen Klassen ist oft unnötig ausführlich und hässlich), aber Sie könnten einigermaßen anderer Meinung sein - es ist ein etwas subjektiver Aufruf.Basierend auf diesem Argument haben die PHP-Entwickler die Warnung in der Sprache beibehalten, oder?
Äh, nicht genau .
Der oben verlinkte PHP-Fehlerbericht 53081 forderte das Löschen der Warnung, da das Hinzufügen des
static::foo()
Konstrukts abstrakte statische Methoden sinnvoll und nützlich gemacht hatte. Rasmus Lerdorf (Schöpfer von PHP) kennzeichnet die Anfrage zunächst als falsch und durchläuft eine lange Kette von schlechten Argumenten, um zu versuchen, die Warnung zu rechtfertigen. Dann findet endlich dieser Austausch statt:Die Behauptung von Rasmus, dass der Code in seinem Beispiel "gut funktioniert", ist falsch; Wie Sie wissen, wird eine strenge Moduswarnung ausgegeben. Ich denke, er hat ohne eingeschalteten strengen Modus getestet. Unabhängig davon ließ ein verwirrter Rasmus die Anfrage fälschlicherweise als "Schwindel" geschlossen.
Und deshalb ist die Warnung immer noch in der Sprache. Dies ist möglicherweise keine ganz zufriedenstellende Erklärung - Sie sind wahrscheinlich hierher gekommen, in der Hoffnung, dass die Warnung rational begründet ist. Leider werden in der realen Welt Entscheidungen manchmal eher aus weltlichen Fehlern und schlechten Argumenten als aus rationalen Entscheidungen getroffen. Dies ist einfach eine dieser Zeiten.
Glücklicherweise hat der geschätzte Nikita Popov die Warnung aus der Sprache in PHP 7 als Teil von PHP RFC entfernt: E_STRICT-Benachrichtigungen neu klassifizieren . Letztendlich hat sich die Vernunft durchgesetzt, und sobald PHP 7 veröffentlicht ist, können wir alle glücklich nutzen,
abstract static
ohne diese dumme Warnung zu erhalten.quelle
Es gibt eine sehr einfache Lösung für dieses Problem, die aus gestalterischer Sicht tatsächlich sinnvoll ist. Wie Jonathan schrieb:
Als Workaround könnten Sie also Folgendes tun:
Und jetzt erzwingen Sie, dass jede Klasse, die MyFoo unterordnet, eine statische Methode getInstance und eine öffentliche Methode getSomeData implementiert. Wenn Sie MyFoo nicht unterordnen, können Sie iMyFoo dennoch implementieren, um eine Klasse mit ähnlichen Funktionen zu erstellen.
quelle
static::
können nützlich sein.abstract static
Methoden haben könnten , ohne PHP zu meckern ...Ich weiß, das ist alt, aber ...
Warum nicht einfach eine Ausnahme für die statische Methode dieser übergeordneten Klasse auslösen? Wenn Sie sie nicht überschreiben, wird die Ausnahme verursacht.
quelle
Ich würde argumentieren, dass eine abstrakte Klasse / Schnittstelle als Vertrag zwischen Programmierern angesehen werden könnte. Es geht mehr darum, wie Dinge aussehen / sich verhalten sollen und nicht um tatsächliche Funktionen. Wie in PHP5.0 und 5.1.x zu sehen ist, ist es kein Naturgesetz, das die PHP-Entwickler daran hindert, sondern der Drang, anderen OO-Entwurfsmustern in anderen Sprachen zu folgen. Grundsätzlich versuchen diese Ideen, unerwartetes Verhalten zu verhindern, wenn man bereits mit anderen Sprachen vertraut ist.
quelle
Ich sehe keinen Grund, statische abstrakte Funktionen zu verbieten. Das beste Argument, dass es keinen Grund gibt, sie zu verbieten, ist, dass sie in Java erlaubt sind. Die Fragen sind: - Sind die technisch machbar? - Ja, da die in PHP 5.2 existierten und sie in Java existieren. Also können wir es tun. SOLLTEN wir es tun? - Machen sie Sinn? Ja. Es ist sinnvoll, einen Teil einer Klasse zu implementieren und einen anderen Teil einer Klasse dem Benutzer zu überlassen. Bei nicht statischen Funktionen ist dies sinnvoll. Warum sollte es bei statischen Funktionen keinen Sinn ergeben? Eine Verwendung statischer Funktionen sind Klassen, in denen nicht mehr als eine Instanz (Singletons) vorhanden sein darf. Zum Beispiel eine Verschlüsselungsmaschine. Es muss nicht in mehreren Fällen vorhanden sein, und es gibt Gründe, dies zu verhindern. Beispielsweise müssen Sie nur einen Teil des Speichers vor Eindringlingen schützen. Daher ist es absolut sinnvoll, einen Teil der Engine zu implementieren und den Verschlüsselungsalgorithmus dem Benutzer zu überlassen. Dies ist nur ein Beispiel. Wenn Sie es gewohnt sind, statische Funktionen zu verwenden, finden Sie noch viel mehr.
quelle
In PHP 5.4+ verwenden Sie das Merkmal:
und in Ihrer Klasse am Anfang setzen:
quelle
abstract public static function get_table_name();
ein Merkmal einfügen und dieses Merkmal in meiner abstrakten Klasse ohne weitere E_STRICT-Warnungen verwenden! Dies erzwang immer noch die Definition der statischen Methode bei den Kindern, wie ich gehofft hatte. Fantastisch!Informieren Sie sich über die Probleme mit der späten statischen Bindung von PHP. Wenn Sie statische Methoden für abstrakte Klassen verwenden, werden Sie wahrscheinlich eher früher als später darauf stoßen. Es ist sinnvoll, dass die strengen Warnungen Sie auffordern, die Verwendung fehlerhafter Sprachfunktionen zu vermeiden.
quelle