Was ist der Unterschied zwischen self :: $ bar und static :: $ bar in PHP?

124

Was ist der Unterschied zwischen selfund staticim folgenden Beispiel?

class Foo
{
    protected static $bar = 1234;

    public static function instance()
    {
        echo self::$bar;
        echo "\n";
        echo static::$bar;
    }

}

Foo::instance();

produziert

1234
1234
cwd
quelle
2
@deceze: Das ist eine ähnliche Frage, aber es ist kein Duplikat. In diesem wird nach der Verwendung der Schlüsselwörter mit Eigenschaften gefragt, während nach der Verwendung dieser Schlüsselwörter mit Konstruktoren gefragt wird.
BoltClock

Antworten:

190

Wenn Sie selfauf ein Klassenmitglied verweisen, beziehen Sie sich auf die Klasse, in der Sie das Schlüsselwort verwenden. In diesem Fall Foodefiniert Ihre Klasse eine geschützte statische Eigenschaft namens $bar. Wenn Sie selfin der FooKlasse auf die Eigenschaft verweisen, verweisen Sie auf dieselbe Klasse.

Wenn Sie also versuchen, eine andere Klasse self::$barin Ihrer FooKlasse zu verwenden, aber eine BarKlasse mit einem anderen Wert für die Eigenschaft haben, wird diese Foo::$baranstelle von verwendet Bar::$bar, was möglicherweise nicht das ist, was Sie beabsichtigen:

class Foo
{
    protected static $bar = 1234;
}

class Bar extends Foo
{
    protected static $bar = 4321;
}

Wenn Sie eine Methode über aufrufen , rufenstatic Sie eine Funktion auf, die als späte statische Bindungen bezeichnet wird (eingeführt in PHP 5.3).

Im obigen Szenario führt die Verwendung selfzu Foo::$bar(1234). Und using staticführt zu Bar::$bar(4321), da mit staticmit der Interpreter die Neudeklaration innerhalb der BarKlasse zur Laufzeit berücksichtigt wird .

Normalerweise verwenden Sie späte statische Bindungen für Methoden oder sogar die Klasse selbst anstelle von Eigenschaften, da Sie Eigenschaften in Unterklassen nicht häufig neu deklarieren. Ein Beispiel für die Verwendung des staticSchlüsselworts zum Aufrufen eines spät gebundenen Konstruktors finden Sie in dieser verwandten Frage: New self vs. new static

Dies schließt jedoch auch die Verwendung staticmit Eigenschaften nicht aus .

BoltClock
quelle
Sie können die untergeordnete Klasse sehr leicht neu deklarieren. Die übergeordnete Klasse ist möglicherweise ein Standardwert, den die untergeordnete Klasse verwendet, sofern sie nicht erneut deklariert. Wenn Sie in der übergeordneten Klasse sind, ist es sicher, self :: zu verwenden, und wenn Sie in einer untergeordneten Klasse sind, könnten Sie ein Argument für die Verwendung einer der beiden Klassen finden, aber self :: funktioniert auch, wenn Sie dies nicht erwarten immer wieder neu deklarieren.
Andrew
3
Gehen Sie zu phpfiddle.org und führen Sie dies aus<?php class Foo { public static $bar = 1234; public static function a( ) { echo 'static'.static::$bar; echo 'self'.self::$bar; } } class Bar extends Foo { public static $bar = 4321; } (new Bar())->a(); ?>
Jewgenij Afanasjew
2
Der Wortlaut der ersten beiden Absätze ist verwirrend, hat ein mehrdeutiges Pronomen, "es", und ist auch redundant, da in späteren Absätzen dieselben Informationen klarer erläutert werden. Ich schlage vor, die ersten beiden Absätze durch den späteren Absatz zu ersetzen, der oben mit "Im obigen Szenario" beginnt. Auf diese Weise steht die unter dem Strich auf den Punkt gebrachte Antwort ganz oben. Es ist klar und leicht zu folgen.
Ahnbizcad
Eine andere Art, darüber nachzudenken: self::$abcWenn es im Inneren verwendet wird, class Fooist es dasselbe wie zu sagen Foo::$abc. Es wird von keiner erneuten Deklaration $abcin einer Unterklasse betroffen sein . AFAIK, der einzige Grund für die Verwendung selfist die Abkürzung, um die Verwendung des Klassennamens zu vermeiden Foo, der möglicherweise länger ist. [Es bedeutet auch, dass Sie den Klassennamen ändern können, ohne all diese Stellen zu ändern - aber das ist meiner Meinung nach kein großer Grund.] (Die Wahl der Namen von PHP ist unglücklich und scheint rückwärts zu sein; "statisch" kann sich ändern - was ist entgegengesetzt zur umgangssprachlichen Bedeutung des natürlichen Wortes "statisch".)
ToolmakerSteve
4

Wie bereits erwähnt, besteht einer der Hauptunterschiede darin, staticdass späte statische Bindungen möglich sind. Eines der nützlichsten Szenarien, das ich gefunden habe, war das Erstellen von Basisklassen für Singleton-Klassen:

class A { // Base Class
    protected static $name = '';
    protected static function getName() {
        return static::$name;
    }
}
class B extends A {
    protected static $name = 'MyCustomNameB';
}
class C extends A {
    protected static $name = 'MyCustomNameC';
}

echo B::getName(); // MyCustomNameB
echo C::getName(); // MyCustomNameC

Bei Verwendung return static::$namein der Basisklasse wird zurückgegeben, was statisch angehängt war, als es erweitert wurde. Wenn Sie sind verwenden , return self::$namedann B::getName()würde eine leere Zeichenfolge zurück , wie das ist , was in der Basisklasse deklariert wird.

ggedde
quelle
0

Mit selfAnruf:

class Foo
{
    protected static $var = 123;
    
    public function getVar()
    {
        return self::$var;
    }
}

class Bar extends Foo
{
    protected static $var = 234;
}

// Displays: "123"
echo (new Bar)->getVar();

Sie können oben sehen, obwohl wir das $varmit unserer BarKlasse überschrieben haben , wird es dennoch zurückgegeben 123, da wir PHP explizit nach der selfVariablen gefragt haben , die wiederum nach der Variablen Foos fragt .

Wenn wir nun den Anruf mit tauschen static, erhalten wir stattdessen den Barüberschriebenen Wert:

Mit staticAnruf:

class Foo
{
    protected static $var = 123;
    
    public function getVar()
    {
        return static::$var;
    }
}

class Bar extends Foo
{
    protected static $var = 234;
}

// Displays: "234"
echo (new Bar)->getVar();
Steve Bauman
quelle