Neues Selbst gegen neue Statik

513

Ich konvertiere eine PHP 5.3-Bibliothek, um mit PHP 5.2 zu arbeiten. Die Hauptsache, die mir im Weg steht, ist die Verwendung einer späten statischen Bindung return new static($options);. Wenn ich diese konvertiere, return new self($options)erhalte ich dann die gleichen Ergebnisse?

Was ist der Unterschied zwischen new selfund new static?

Mike
quelle

Antworten:

890

bekomme ich die gleichen Ergebnisse?

Nicht wirklich. Ich kenne jedoch keine Problemumgehung für PHP 5.2.

Was ist der Unterschied zwischen new selfund new static?

selfbezieht sich auf dieselbe Klasse, in der das newSchlüsselwort tatsächlich geschrieben ist.

staticbezieht sich in den späten statischen Bindungen von PHP 5.3 auf jede Klasse in der Hierarchie, für die Sie die Methode aufgerufen haben.

Erbt im folgenden Beispiel Bbeide Methoden von A. Der selfAufruf ist gebunden, Aweil er in Ader Implementierung der ersten Methode definiert ist, während er statican die aufgerufene Klasse gebunden ist (siehe auch get_called_class()).

class A {
    public static function get_self() {
        return new self();
    }

    public static function get_static() {
        return new static();
    }
}

class B extends A {}

echo get_class(B::get_self());  // A
echo get_class(B::get_static()); // B
echo get_class(A::get_self()); // A
echo get_class(A::get_static()); // A
BoltClock
quelle
macht Sinn. Ich denke, die beste Wette ist es, den Klassennamen an die Funktion zu übergeben, die eine späte statische Bindung verwendet, und dann neuen $ className ($ options) zurückzugeben.
Mike
12
Sie müssen den Klassennamen nicht "übergeben", das können Sie immer tun get_called_class(), was praktisch dasselbe ist __CLASS__, aber LSB-kompatibel.
Schattenhand
7
get_called_class existiert in <PHP5.3 nicht. Daher, wenn Sie den Klassennamen des instanziierten Objekts in PHP5.2 erhalten möchten. Diese Funktion hilft nicht, wenn Sie versuchen, eine Bibliothek von PHP 5.3 nach PHP 5.2 zu konvertieren
txwikinger
2
Die als self :: theFunction () aufgerufene Funktion verhält sich wie "Ich werde im Kontext der Klasse ausführen, zu der ich physisch gehöre." und die als static :: theFunction () aufgerufene Funktion verhält sich wie "Ich werde im Kontext der Klasse ausführen, die tatsächlich von der Außenwelt aufgerufen wurde". (Angenommen, das Vererbungsszenario). Danke
Shubhranshu
2
In meinem Kopf nehme ich einfach das, was intuitiv ist, und mache es umgekehrt. Sie würden denken, basierend auf der Benennung, selfwürden sich selbst zurückgeben und staticetwas zurückgeben, das nicht überschrieben werden kann ... Aber siehe da, es ist das Gegenteil. Ich bin immer wieder beeindruckt von der Benennung, den Konventionen und dem allgemeinen Stil von PHP. -_-
Ahnbizcad
23

Wenn die Methode dieses Codes nicht statisch ist, können Sie mithilfe von 5.2 eine Problemumgehung erhalten get_class($this).

class A {
    public function create1() {
        $class = get_class($this);
        return new $class();
    }
    public function create2() {
        return new static();
    }
}

class B extends A {

}

$b = new B();
var_dump(get_class($b->create1()), get_class($b->create2()));

Die Ergebnisse:

string(1) "B"
string(1) "B"
Marius Balčytis
quelle
17
Wenn die Methode nicht statisch ist, sind späte statische Bindungen völlig irrelevant.
BoltClock
1
Sie können es beispielsweise in der Methode "Kopieren" verwenden, bei der das Objekt ohne Verwendung kopiert wird clone, sondern nur durch erneutes Erstellen und Festlegen der Eigenschaften. $copy = new static(); $copy->set($this->get()); return $copy;
Marius Balčytis
9
@ BoltClock Sicher nicht? Wenn Sie eine überschriebene statische Methode aus einer Instanzmethode einer Unterklasse heraus aufrufen, hat Ihre Auswahl self::oder static::Auswirkung Einfluss darauf, ob die Version dieser statischen Methode der Basisklasse oder der Unterklasse verwendet wird. In Ermangelung eines Grundes zu der Annahme, dass eine solche Situation von Natur aus auf eine schlechte Praxis hinweist (und ich sehe keinen Grund, warum dies so sein sollte), ist die Wahl zwischen self::und static::innerhalb nicht statischer Methoden genauso relevant wie in statische Methoden. Habe ich Ihren Kommentar falsch verstanden oder ist einer von uns einfach falsch?
Mark Amery
4
@ Mark Amery: Hmm, daran habe ich nicht gedacht. Du hast absolut recht. Ich hatte angenommen, dass in der fraglichen Instanzmethode keine statischen Methoden aufgerufen werden würden, aber anhand Ihres Beispiels kann ich sehen, dass dies eine sehr naive Annahme wäre.
BoltClock
Späte statische Bindungen doc => php.net/manual/en/language.oop5.late-static-bindings.php
DevWL
7

Zusätzlich zu den Antworten anderer:

static :: wird anhand von Laufzeitinformationen berechnet.

Das bedeutet, dass Sie static::in einer Klasseneigenschaft keine Eigenschaften verwenden können, weil Eigenschaften:

Muss zur Kompilierungszeit ausgewertet werden können und darf nicht von Laufzeitinformationen abhängen.

class Foo {
    public $name = static::class;

}

$Foo = new Foo;
echo $Foo->name; // Fatal error

Verwenden von self::

class Foo {
    public $name = self::class;

}
$Foo = new Foo;
echo $Foo->name; // Foo

Bitte beachten Sie, dass der schwerwiegende Fehlerkommentar in dem von mir erstellten Code nicht angibt, wo der Fehler aufgetreten ist. Der Fehler ist früher aufgetreten, bevor das Objekt als @Grapestain instanziiert wurde, wie in den Kommentaren erwähnt

Regen
quelle
4
Beachten Sie, dass der Fehler in Zeile 2 public $name = static::class;und nicht in Zeile 7 ausgegeben wird, wie im Beispiel vorgeschlagen. Der Fehler lautet: "static :: class kann nicht für die Auflösung von Klassennamen zur Kompilierungszeit verwendet werden", was darauf hinweist, dass das Problem nicht darin besteht, dass Sie versuchen, auf das Feld $ name zuzugreifen, sondern weit zuvor bei der Kompilierung der PHP-Klasse. Zeile 7 (oder 6) wird im ersten Beispiel nicht erreicht.
sbnc.eu
@Grapestain Der Kommentar, den ich im Beispiel gemacht habe, war, das Endergebnis zu zeigen und nicht anzugeben, wo tatsächlich ein Fehler aufgetreten ist. Aber trotzdem danke, dass du darauf hingewiesen hast.
Regen
Richtig, ich wollte nicht kritisieren, sondern nur klarstellen, was mich zuerst verwirrte, in der Hoffnung, dass es anderen helfen könnte. Trotzdem ein hilfreiches Beispiel!
sbnc.eu