Vorbereitungen für ein PHP-Interview: Das statische Schlüsselwort

  • Tutorial
Es ist kein Geheimnis, dass sie bei Interviews gerne knifflige Fragen stellen. Nicht immer angemessen, nicht immer realitätsbezogen, aber die Tatsache bleibt - fragen Sie. Natürlich ist die Frage umstritten, und manchmal zielt die Frage, die Ihnen auf den ersten Blick albern vorkommt, darauf ab, zu überprüfen, wie gut Sie die Sprache beherrschen, in der Sie schreiben.

Bild

Versuchen wir, eine dieser Fragen zu analysieren: Was bedeutet das Wort "statisch" in PHP und warum wird es verwendet?

Das statische Schlüsselwort in PHP hat drei verschiedene Bedeutungen. Wir werden sie in chronologischer Reihenfolge analysieren, wie sie in der Sprache erschienen sind.

Der erste Wert ist eine statische lokale Variable


function foo() {
  $a = 0;
  echo $a;
  $a = $a + 1;
}
foo(); // 0
foo(); // 0
foo(); // 0


In PHP sind Variablen lokal. Dies bedeutet, dass eine Variable, die innerhalb einer Funktion (Methode) definiert und einen Wert erhalten hat, nur während der Ausführung dieser Funktion (Methode) existiert. Wenn Sie die Methode beenden, wird die lokale Variable zerstört und bei erneuter Eingabe neu erstellt. Im obigen Code ist eine solche lokale Variable die Variable $ a - sie existiert nur innerhalb der Funktion foo () und wird jedes Mal neu erstellt, wenn diese Funktion aufgerufen wird. Das Inkrementieren einer Variablen in diesem Code ist bedeutungslos, da die Funktion in der nächsten Codezeile ihre Arbeit beendet und der Wert der Variablen verloren geht. Egal, wie oft wir die Funktion foo () aufrufen, sie gibt immer 0 aus

. Alles ändert sich jedoch, wenn wir das Schlüsselwort static vor der Zuweisung festlegen:

function foo() {
  static $a = 0;
  echo $a;
  $a = $a + 1;
}
foo(); // 0
foo(); // 1
foo(); // 2


Das statische Schlüsselwort, das vor dem Zuweisen eines Werts zu einer lokalen Variablen geschrieben wurde, hat folgende Auswirkungen:
  1. Die Zuordnung wird nur einmal durchgeführt, wenn die Funktion zum ersten Mal aufgerufen wird
  2. Der Wert der so markierten Variablen wird nach Beendigung der Funktion gespeichert
  3. Bei nachfolgenden Aufrufen der Funktion erhält die Variable anstelle der Zuweisung den zuvor gespeicherten Wert

Diese Verwendung des Wortes static wird als statische lokale Variable bezeichnet .

Fallstricke statischer Variablen

Natürlich kann es, wie immer in PHP, nicht ohne "Fallstricke" auskommen.

Einer statischen Variablen können nur Konstanten oder konstante Ausdrücke zugewiesen werden. Hier ist der Code:
static $a = bar();

zwangsläufig zu einem Parser-Fehler führen. Glücklicherweise wurde es ab Version 5.6 möglich, nicht nur Konstanten, sondern auch konstante Ausdrücke (zum Beispiel „1 + 2“ oder „[1, 2, 3]“) zuzuweisen, dh Ausdrücke, die unabhängig von anderem Code und sind kann in der Erstellungsphase berechnet werden.

Zweite Stein - Methoden existieren in einer einzigen Kopie.
Hier ist alles etwas komplizierter. Um das Wesentliche zu verstehen, gebe ich den Code:
class A {
  public function foo() {
    static $x = 0;
    echo ++$x;
  }
}
$a1 = new A;
$a2 = new A;
$a1->foo(); // 1
$a2->foo(); // 2
$a1->foo(); // 3
$a2->foo(); // 4

Entgegen der intuitiven Erwartung von „verschiedenen Objekten - verschiedenen Methoden“ sehen wir in diesem Beispiel deutlich, dass sich dynamische Methoden in PHP „nicht multiplizieren“. Selbst wenn wir einhundert Objekte dieser Klasse haben, wird die Methode nur in einer Instanz existieren, nur bei jedem Aufruf wird ein anderes $ in sie geworfen.

Dieses Verhalten kann für einen nicht vorbereiteten Entwickler unerwartet sein und als Fehlerquelle dienen. Es ist zu beachten, dass die Vererbung der Klasse (und der Methode) dazu führt, dass noch eine neue Methode erstellt wird:

class A {
  public function foo() {
    static $x = 0;
    echo ++$x;
  }
}
class B extends A {
}
$a1 = new A;
$b1 = new B;
$a1->foo(); // 1
$b1->foo(); // 1
$a1->foo(); // 2
$b1->foo(); // 2


Fazit: Dynamische Methoden in PHP existieren im Kontext von Klassen, nicht von Objekten. Und nur zur Laufzeit ist die Ersetzung "$ this = current_object"

Der zweite Wert - statische Eigenschaften und Klassenmethoden


Im PHP-Objektmodell können Eigenschaften und Methoden nicht nur für Objekte - Instanzen der Klasse, sondern auch für die gesamte Klasse - festgelegt werden. Dazu wird auch das Schlüsselwort static verwendet:

class A {
  public static $x = 'foo';
  public static function test() {
    return 42;
  }
}
echo A::$x; // 'foo'
echo A::test(); // 42

Um auf diese Eigenschaften und Methoden zuzugreifen, werden Doppelpunktkonstruktionen ("Paamayim Nekudotayim") verwendet, z. B. CLASS_NAME :: $ Variable_NAME und CLASS_NAME :: MethodName ().

Es versteht sich von selbst, dass statische Eigenschaften und statische Methoden ihre eigenen Eigenschaften und "Fallstricke" haben, die Sie kennen müssen.

Das erste Merkmal ist alltäglich - es gibt kein $ dies. Tatsächlich ergibt sich dies aus der Definition einer statischen Methode - da sie einer Klasse und keinem Objekt zugeordnet ist, ist die Pseudovariable $ this darin nicht verfügbar, die das aktuelle Objekt in dynamischen Methoden angibt. Welches ist völlig logisch.

Sie müssen jedoch wissen, dass PHP im Gegensatz zu anderen Sprachen die Situation "$ this is written in the static method" beim Parsen oder Kompilieren nicht bestimmt. Ein ähnlicher Fehler kann nur zur Laufzeit auftreten, wenn Sie versuchen, Code mit $ this innerhalb einer statischen Methode auszuführen.

Ein Code wie dieser:
class A {
  public $id = 42;
  static public function foo() {
    echo $this->id;
  }
}

wird erst zu Fehlern führen, wenn Sie versuchen, die foo () -Methode unangemessen zu verwenden:
$a = new A;
$a->foo();
(und sofort "Schwerwiegender Fehler: Verwenden von $ this, wenn nicht im Objektkontext")

Das zweite Feature - Static ist kein Axiom!
class A {
  static public function foo() {
    echo 42;
  }
}
$a = new A;
$a->foo();

Ja ja Eine statische Methode kann in einem dynamischen Kontext wie eine Objektmethode aufgerufen werden, wenn sie $ this nicht im Code enthält. Dies ist kein Fehler in PHP.

Das Gegenteil ist nicht ganz richtig:
class A {
  public function foo() {
    echo 42;
  }
}
A::foo();

Eine dynamische Methode, die $ this nicht verwendet, kann in einem statischen Kontext ausgeführt werden. Sie erhalten jedoch die Warnung „Nicht statische Methode A :: foo () sollte nicht statisch aufgerufen werden“ der Stufe E_STRICT. Es liegt an Ihnen, entweder die Codestandards genau einzuhalten oder Warnungen zu unterdrücken. Das erste ist natürlich vorzuziehen.

Übrigens gilt alles, was oben steht, nur für Methoden. Die Verwendung einer statischen Eigenschaft durch "->" ist nicht möglich und führt zu einem schwerwiegenden Fehler.

Die dritte Bedeutung, die am schwierigsten zu sein scheint - die späte statische Bindung


Die Entwickler der PHP-Sprache hörten nicht bei zwei Werten des Schlüsselworts „static“ auf und fügten in Version 5.3 ein weiteres „Feature“ der Sprache hinzu, das durch dasselbe Wort implementiert wird! Es wird "Late Static Binding" oder LSB (Late Static Binding) genannt.

Das Wesen von LSB lässt sich am einfachsten anhand einfacher Beispiele verstehen:

class Model {
  public static $table = 'table';
  public static function getTable() {
    return self::$table;
  }
}
echo Model::getTable(); // 'table'

Das Schlüsselwort self in PHP bedeutet immer "der Name der Klasse, in der dieses Wort geschrieben ist". In diesem Fall wird self durch die Model-Klasse und self :: $ table durch Model :: $ table ersetzt.
Diese Sprachfunktion wird als "frühe statische Bindung" bezeichnet. Warum früh? Denn die Bindung von self und einem konkreten Klassennamen erfolgt nicht zur Laufzeit, sondern zu einem früheren Zeitpunkt - dem Parsen und Kompilieren von Code. Sondern „statisch“ - weil es sich um statische Eigenschaften und Methoden handelt.

Lassen Sie uns unseren Code ein wenig ändern:

class Model {
  public static $table = 'table';
  public static function getTable() {
    return self::$table;
  }
}
class User extends Model {
  public static $table = 'users';
}
echo User::getTable(); // 'table'


Jetzt verstehen Sie, warum PHP in dieser Situation nicht intuitiv ist. self wurde der Model-Klasse zugeordnet, als die User-Klasse noch nicht bekannt war, und verweist daher auf Model.

Wie zu sein

Um dieses Dilemma zu lösen, wurde in der Laufzeit ein „später“ Bindungsmechanismus erfunden. Es funktioniert sehr einfach - schreiben Sie einfach "static" anstelle des Wortes "self" und die Verbindung wird mit der Klasse hergestellt, die den angegebenen Code aufruft, und nicht mit der Klasse, in der er geschrieben ist:
class Model {
  public static $table = 'table';
  public static function getTable() {
    return static::$table;
  }
}
class User extends Model {
  public static $table = 'users';
}
echo User::getTable(); // 'users'


Dies ist die mysteriöse "späte statische Bindung".

Es sollte beachtet werden, dass es in PHP zur Vereinfachung zusätzlich zum Wort "static" eine spezielle Funktion get_called_class () gibt, die Ihnen mitteilt, in welcher Klasse Ihr Code gerade ausgeführt wird.

Habt ein tolles Vorstellungsgespräch!

Die Liste der nützlichen Links zum Handbuch:

Jetzt auch beliebt: