Frage

Nach dem Aktivieren der strengen Warnungen in PHP 5.2, sah ich eine Last von strengen Standards Warnungen von 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 Klasse-Programm und wird abstrakt statisch deklariert, weil sie in den untergeordneten Klassen umgesetzt werden sollen, wie TVProgram.

Ich habe Verweise auf diese Änderung finden hier :

  

Dropped abstrakte statische Klasse-Funktionen. Durch ein Versehen, PHP 5.0.x und 5.1.x abstrakte statische Funktionen in Klassen erlaubt. Ab PHP 5.2.x, können sie nur Schnittstellen haben.

Meine Frage ist: kann jemand in einer klaren Art und Weise erklären, warum es nicht eine abstrakte statische Funktion in PHP sein sollte

War es hilfreich?

Lösung

statische Methoden gehören zu der Klasse, die sie erklärt. Wenn die Klasse erweitern, können Sie eine statische Methode mit dem gleichen Namen erstellen, aber Sie sind nicht in der Tat eine statische abstrakte Methode zu implementieren.

Das Gleiche gilt jede Klasse mit statischen Methoden für die Erweiterung. Wenn Sie diese Klasse erweitern und eine statische Methode der gleichen Signatur erstellen, werden tatsächlich zwingende Sie nicht die statische Methode der übergeordneten Klasse

EDIT (16. September 2009)
Aktualisieren Sie zu diesem Thema. Ausführen von PHP 5.3, ich sehe abstrakt statisch ist zurück, für gut oder schlecht. (Siehe http://php.net/lsb für weitere Informationen)

KORREKTUR (von philfreo)
abstract static ist nach wie vor nicht erlaubt in PHP 5.3, LSB verwandt ist aber anders.

Andere Tipps

Es ist eine lange, traurige Geschichte.

Wenn PHP 5.2 erste Warnung eingeführt, Späte statische Bindung in der Sprache noch nicht waren. Falls Sie sich nicht mit Später statischer Bindung, beachten Sie, dass Code wie dies die Art und Weise funktioniert man erwarten könnte:

<?php

abstract class ParentClass {
    static function foo() {
        echo "I'm gonna do bar()";
        self::bar();
    }

    abstract static function bar();
}

class ChildClass extends ParentClass {
    static function bar() {
        echo "Hello, World!";
    }
}

ChildClass::foo();

die Strict-Modus Warnung Abgesehen, wird der Code oben nicht funktionieren. Der self::bar() Anruf in foo() bezieht sich explizit auf die bar() Methode von ParentClass, auch wenn foo() als Methode des ChildClass genannt wird. Wenn Sie versuchen, diesen Code mit striktem Modus ausgeschaltet zu laufen, werden Sie sehen " PHP Fatal error: Kann nicht nennen abstrakte Methode Parent :: bar () ".

Vor diesem Hintergrund, abstrakte statische Methoden in PHP 5.2 waren nutzlos. Die ganze Punkt eine abstrakte Methode ist, dass Sie Code schreiben, der die Methode aufruft, ohne zu wissen, was die Umsetzung es ruft sein würde - und dann verschiedene Implementierungen auf verschiedenen Kind-Klassen bieten. Aber da PHP 5.2 keine saubere Art und Weise bietet ein Verfahren zur Herstellung einer übergeordneten Klasse zu schreiben, die eine statische Methode der Kind-Klasse aufruft, auf das sie genannt wird, diese Verwendung von abstrakten statischen Methoden ist nicht möglich. Daher jede Nutzung von abstract static in PHP 5.2 ist schlechter Code, inspirierte wahrscheinlich von einem Missverständnis, wie das self Schlüsselwort funktioniert. Es war ganz vernünftig, eine Warnung über diese zu werfen.

Aber dann PHP 5.3 kam in der Fähigkeit zusammen hinzugefügt, um die Klasse zu verweisen, auf das ein Verfahren über das static Stichwort genannt wurde (im Gegensatz zum self Schlüsselwort, das zu der Klasse bezieht sich immer in dem das Verfahren war definiert ). Wenn Sie self::bar() ändern oben in meinem Beispiel static::bar(), es funktioniert in PHP 5.3 fein und darüber. Sie können mehr über self vs static unter New Selbst gegen neue statische .

Mit dem Schlüsselwort static hinzugefügt, das klare Argument dafür, dass abstract static eine Warnung werfen war verschwunden. Späte statische Hauptzweck Bindings war Methoden in einer übergeordneten Klasse definiert, damit statische Methoden aufrufen, die in untergeordneten Klassen definiert werden würde; abstrakte statische Methoden erlauben scheint vernünftig und konsequent die Existenz Späte statische Bindung gegeben.

Sie noch könnte, glaube ich, einen Fall machen die Warnung zu halten. Zum Beispiel könnte man argumentieren, dass seit PHP können Sie statische Methoden der abstrakten Klassen nennen, in meinem Beispiel oben (auch nachdem er Festsetzung von self mit static ersetzen) Sie aussetzt eine öffentliche Methode ParentClass::foo() welches gebrochen und dass Sie nicht wirklich wollen, belichten. eine nicht-statische Klasse verwenden - das heißt, alle Methoden Instanzmethoden machen und machen die Kinder ParentClass alle Singletons oder etwas sein - würde dieses Problem lösen, da ParentClass, abstrakt zu sein, kann nicht und so kann seine Instanzmethoden instanziiert werden ‚t genannt werden. Ich denke, dieses Argument schwach ist (weil ich ParentClass::foo() denke auszusetzen keine große Sache ist und Singletons anstelle von statischen Klassen ist oft unnötig ausführlich und hässlich), aber man vernünftigerweise nicht zustimmen - es ist ein wenig subjektiv Anruf

. So

basierend auf dieses Argument, der PHP-Entwickler hielt die Warnung in der Sprache, nicht wahr?

Uh, nicht genau .

PHP Bug-Report 53081, oben verbunden, für die Warnung genannt fallen gelassen werden, da die Zugabe des static::foo() Konstrukts abstrakte statische Methoden sinnvoll und nützlich gemacht hatte. Rasmus Lerdorf (Schöpfer von PHP) beginnt mit der Markierung der Anfrage als Schein und geht durch eine lange Kette von schlechter Argumentation aus, um zu versuchen, die Warnung zu rechtfertigen. Dann, endlich, dieser Austausch takes Ort:

  

Giorgio

     

Ich weiß, aber:

abstract class cA
{
      //static function A(){self::B();} error, undefined method
      static function A(){static::B();} // good
      abstract static function B();
}

class cB extends cA
{
    static function B(){echo "ok";}
}

cB::A();
     

Rasmus

     

Richtig, das ist genau, wie es funktionieren soll.

     

Giorgio

     

, aber es ist nicht erlaubt: (

     

Rasmus

     

Was nicht erlaubt ist?

abstract class cA {
      static function A(){static::B();}
      abstract static function B();
}

class cB extends cA {
    static function B(){echo "ok";}
}

cB::A();
     

Das funktioniert gut. Sie können natürlich nicht selbst anrufen :: B (), aber statisch :: B ()   ist in Ordnung.

Die Behauptung von Rasmus, dass der Code in seinem Beispiel „funktioniert gut“ ist falsch; wie Sie wissen, wirft es eine strikte Modus Warnung. Ich glaube, er testet ohne Strict-Modus eingeschaltet. Unabhängig davon, links ein verwirrter Rasmus die Anfrage fälschlicherweise geschlossen als „Schein“.

Und das ist, warum die Warnung noch in der Sprache ist. Dies kann nicht eine völlig befriedigende Erklärung sein - Sie wahrscheinlich kamen hier die Hoffnung, es eine rationale Rechtfertigung der Warnung war. Leider ist in der realen Welt, werden manchmal Entscheidungen geboren aus banalen Fehlern und schlechter Argumentation nicht aus rationaler Entscheidungsfindung. Das ist einfach eine jener Zeiten.

Zum Glück hat sich die schätzbar Nikita Popov die Warnung aus der Sprache in PHP 7 als Teil der PHP RFC entfernt: Neueinstufung E_STRICT bemerkt . Letztlich hat Vernunft durchgesetzt, und einmal PHP 7 freigegeben wird, wir alle glücklich abstract static ohne Empfang dieses dumme Warnung verwenden können.

Es ist eine sehr einfache Arbeit um für dieses Problem, die tatsächlich Sinn von einer Design-Sicht macht. Als Jonathan schrieb:

  

Das Gleiche gilt jede Klasse mit statischen Methoden für die Erweiterung. Wenn Sie diese Klasse erweitern und eine statische Methode der gleichen Signatur erstellen, werden tatsächlich zwingende Sie nicht die statische Methode der übergeordneten Klasse

So, wie eine Arbeit um Sie könnte dies tun:

<?php
abstract class MyFoo implements iMyFoo {

    public static final function factory($type, $someData) {
        // don't forget checking and do whatever else you would
        // like to do inside a factory method
        $class = get_called_class()."_".$type;
        $inst = $class::getInstance($someData);
        return $inst;
    }
}


interface iMyFoo {
    static function factory($type, $someData);
    static function getInstance();
    function getSomeData();
}
?>

Und Sie nun erzwingen, dass jede Klasse Subklassifizieren MyFoo implementiert eine getInstance statische Methode, und eine öffentliche getSomeData Methode. Und wenn Sie MyFoo nicht Unterklasse, können Sie immer noch iMyFoo implementieren eine Klasse mit ähnlicher Funktionalität zu schaffen.

Ich weiß, das ist alt, aber ....

Warum nicht einfach eine Ausnahme aus, das die statische Methode der übergeordneten Klasse, auf diese Weise, wenn Sie es die Ausnahme verursacht wird, nicht außer Kraft setzen.

Ich würde argumentieren, dass eine abstrakte Klasse / Schnittstelle als einen Vertrag zwischen Programmierer gesehen werden kann. Es befasst sich mehr mit, wie die Dinge aussehen sollte / verhalten sich wie und nicht die tatsächliche Funktionalität implementieren. Wie in PHP5.0 und 5.1.x gesehen ist es kein Naturgesetz, das den PHP-Entwickler zu tun, es verhindert, aber der Drang, mit anderen OO-Design-Mustern in anderen Sprachen zu gehen. Grundsätzlich versuchen diese Ideen ein unerwartetes Verhalten zu vermeiden, wenn man bereits mit anderen Sprachen ist.

Ich sehe keinen Grund, statische abstrakte Funktionen zu verbieten. Das beste Argument, dass es keinen Grund, sie zu verbieten ist, dass sie in Java erlaubt sind. Die Fragen sind: - Ist die technisch machbar? - Ja, da die 5.2 in PHP existiert und sie existieren in Java. So WHE kann es tun. Sollten wir es tun? - Haben sie sinnvoll? Ja. Es macht Sinn, einen Teil einer Klasse zu implementieren und einen anderen Teil einer Klasse dem Benutzer überlassen. Es macht Sinn, in nicht-statischen Funktionen, warum soll es nicht sinnvoll, für statische Funktionen machen? Eine Verwendung von statischen Funktionen sind Klassen, in denen es darf nicht mehr als eine Instanz (Singletons) sein. Zum Beispiel einer Verschlüsselungs-Engine. Es muss nicht in mehreren Fällen existieren und es gibt Gründe, dies zu verhindern - zum Beispiel, müssen Sie nur ein Teil des Speichers vor Eindringlingen schützen. So macht es durchaus Sinn, einen Teil des Motors zu implementieren und den Verschlüsselungsalgorithmus für den Benutzer verlassen. Dies ist nur ein Beispiel. Wenn Sie statische Funktionen zu verwenden sind es gewohnt, finden Sie viele mehr.

In PHP 5.4+ Verwendung Merkmal:

trait StaticExample {
    public static function instance () {
    return new self;
    }
}

und in der Klasse sich am Anfang gesagt:

use StaticExample;

Schauen Sie in PHP ‚Späte statische Bindung‘ Fragen. Wenn Sie statische Methoden auf abstrakte Klassen setzen sind, wirst du wahrscheinlich in es eher früher als später laufen. Es macht Sinn, dass die strengen Warnungen Sie sagen Funktionen mit gebrochener Sprache zu vermeiden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top