Was genau ist Späte statische Bindung in PHP?
-
19-09-2019 - |
Frage
Was genau ist Späte statische Bindung in PHP?
Lösung
Sie müssen auf jeden Fall Späte statische Bindung lesen in dem PHP-Handbuch. Ich werde jedoch versuchen Sie eine kurze Zusammenfassung zu geben.
Im Grunde läuft es auf die Tatsache, dass das self
Schlüsselwort nicht den gleichen Regeln der Vererbung folgt. self
löst sich immer auf die Klasse, in der sie verwendet wird. Dies bedeutet, dass wenn Sie eine Methode in einer übergeordneten Klasse zu machen und es von einem Kind Klasse aufrufen, self
wird das Kind nicht verweisen wie man erwarten könnte.
Späte statische Bindung stellt eine neue Verwendung für das static
Schlüsselwort, das dieses besondere Manko behebt. Wenn Sie static
verwenden, stellt es die Klasse, wo Sie es zuerst verwenden, das heißt. es bindet 'auf die Laufzeitklasse.
Das sind die beiden grundlegenden Konzepte dahinter. Die Art und Weise self
, parent
und static
arbeiten, wenn static
im Spiel ist subtil sein kann, so anstatt zu gehen, um Details, würde ich empfehlen, dass Sie die Manpage Beispiele zu studieren. Sobald Sie die Grundlagen der einzelnen Keywords zu verstehen, sind die Beispiele durchaus notwendig, um zu sehen, was für Ergebnisse, die Sie bekommen werden.
Andere Tipps
Ab PHP 5.3.0, PHP implementiert eine Funktion späte statische Bindung aufgerufen, die verwendet werden kann, die gerufene Klasse im Rahmen der statischen Vererbung zu verweisen.
Späte statische Versuche verbindlich diese Einschränkung zu lösen, indem ein Schlüsselwort, das verweist auf die Klasse einzuführen, die ursprünglich zur Laufzeit aufgerufen wurden. Es wurde beschlossen, nicht ein neues Schlüsselwort einzuführen, sondern static
verwenden, die bereits reserviert wurde.
Lassen Sie uns ein Beispiel sehen:
<?php
class Car
{
public static function run()
{
return static::getName();
}
private static function getName()
{
return 'Car';
}
}
class Toyota extends Car
{
public static function getName()
{
return 'Toyota';
}
}
echo Car::run(); // Output: Car
echo Toyota::run(); // Output: Toyota
?>
late static bindings
Arbeit durch die Klasse in der letzten „Nicht-Anrufweiterschaltung“ genannt zu speichern. Bei statischen Methodenaufrufen, ist dies die Klasse explizit genannt (in der Regel auf der linken Seite des :: operator); bei nicht-statischer Methode Anrufe, es ist die Klasse des Objekts.
A "Anrufweiterschaltung" ist ein statische, die von self::
eingeführt wird, parent::
, static::
, oder, wenn in der Klassenhierarchie steigen, forward_static_call()
.
Die Funktion get_called_class()
verwendet werden kann, eine Zeichenfolge mit dem Namen der aufgerufenen Klasse abzurufen und static::
stellt seinen Umfang.
Es ist nicht sehr offensichtlich Verhalten:
Der folgende Code erzeugt 'alpha'.
class alpha {
function classname(){
return __CLASS__;
}
function selfname(){
return self::classname();
}
function staticname(){
return static::classname();
}
}
class beta extends alpha {
function classname(){
return __CLASS__;
}
}
$beta = new beta();
echo $beta->selfname(); // Output: alpha
echo $beta->staticname(); // Output: beta
Wenn wir jedoch die Erklärung der Funktion Klassennamen aus der Beta-Klasse entfernen, wir bekommen ‚alphaalpha‘ als Ergebnis.
Ich zitiere aus dem Buch: „PHP-Master-Schreib topaktuelle Code“.
Späte statische Bindung war ein Feature mit PHP 5.3 eingeführt. Es erlaubt wir zu vererben statischen Methoden von einer übergeordneten Klasse und zu Referenz das Kind Klasse aufgerufen wird.
Diese Mittel können Sie eine abstrakte Klasse mit statischen Methoden haben, und Verweisen Sie auf die konkrete Implementierungen des Kindes Klasse durch die Verwendung von static :: Methode () Notation anstelle der Selbst :: Methode ().
Sie können ferner einen Blick auf die offizielle PHP-Dokumentation zu nehmen, wie gut: http://php.net/manual/en/language. oop5.late-static-bindings.php
Der klarste Weg zu erklären Späte statische Bindung mit einem einfachen Beispiel. Werfen Sie einen Blick auf die beiden Klassendefinitionen unten und lesen Sie weiter.
class Vehicle {
public static function invokeDriveByStatic() {
return static::drive(); // Late Static Binding
}
public static function invokeStopBySelf() {
return self::stop(); // NOT Late Static Binding
}
private static function drive(){
return "I'm driving a vehicle";
}
private static function stop(){
return "I'm stopping a vehicle";
}
}
class Car extends Vehicle {
protected static function drive(){
return "I'm driving a CAR";
}
private static function stop(){
return "I'm stopping a CAR";
}
}
Wir sehen eine Übergeordnete Klasse (Fahrzeug) und eine Kinderklasse (Auto). Die Parent-Klasse hat zwei öffentliche Methoden:
-
invokeDriveByStatic
-
invokeStopBySelf
Die Parent-Klasse hat auch 2 private Methoden:
-
drive
-
stop
Die Child-Klasse überschreibt 2 Methoden:
-
drive
-
stop
Jetzt ist invoke die öffentlichen Methoden lassen:
-
invokeDriveByStatic
-
invokeStopBySelf
Fragen Sie sich: Welche Klasse aufruft invokeDriveByStatic
/ invokeStopBySelf
? Der Elternteil oder Kind Klasse?
Werfen Sie einen Blick unter:
// This is NOT Late Static Binding
// Parent class invokes from Parent. In this case Vehicle.
echo Vehicle::invokeDriveByStatic(); // I'm driving a vehicle
echo Vehicle::invokeStopBySelf(); // I'm stopping a vehicle
// This is Late Static Binding.
// Child class invokes an inherited method from Parent.
// Child class = Car, Inherited method = invokeDriveByStatic().
// ...
// The inherited method invokes a method that is overridden by the Child class.
// Overridden method = drive()
echo Car::invokeDriveByStatic(); // I'm driving a CAR
// This is NOT Late Static Binding
// Child class invokes an inherited method from Parent.
// The inherited method invokes a method inside the Vehicle context.
echo Car::invokeStopBySelf(); // I'm stopping a vehicle
Das static
Schlüsselwort wird in einem Singleton-Entwurfsmuster verwendet.
Siehe Link: https://refactoring.guru/design-patterns/singleton/php/example
Das einfachste Beispiel den Unterschied zeigen.
Beachten Sie, self :: $ c
class A
{
static $c = 7;
public static function getVal()
{
return self::$c;
}
}
class B extends A
{
static $c = 8;
}
B::getVal(); // 7
Späte statische Bindung, note static :: $ c
class A
{
static $c = 7;
public static function getVal()
{
return static::$c;
}
}
class B extends A
{
static $c = 8;
}
B::getVal(); // 8
Zum Beispiel:
abstract class Builder {
public static function build() {
return new static;
}
}
class Member extends Builder {
public function who_am_i() {
echo 'Member';
}
}
Member::build()->who_am_i();
Betrachtet man es von einem „warum sollte ich diese verwenden?“ Perspektive, es ist im Grunde eine Möglichkeit, den Kontext zu ändern, von dem die statischen Methode interpretiert / ausgeführt wird.
Mit self
, ist der Kontext, die, wo Sie die Methode ursprünglich definiert. Mit static
, dann ist es die, die Sie aus sind aufgerufen wird.
Auch sehen, wenn Sie statische Variablen in Klassen Kind aktualisieren. Ich fand diese (etwas) unerwartetes Ergebnis in dem Kind B Updates Kind C:
class A{
protected static $things;
}
class B extends A {
public static function things(){
static::$things[1] = 'Thing B';
return static::$things;
}
}
class C extends A{
public static function things(){
static::$things[2] = 'Thing C';
return static::$things;
}
}
print_r(C::things());
// Array (
// [2] => Thing C
// )
B::things();
print_r(C::things());
// Array (
// [2] => Thing C
// [1] => Thing B
// )
Sie können das Problem beheben, indem Sie die gleiche Variable in jedem Kind Klasse deklarieren, zum Beispiel:
class C extends A{
protected static $things; // add this and B will not interfere!
public static function things(){
static::$things[2] = 'Thing C';
return static::$things;
}
}