Spätes statisches Binden
Teil des Abschnitts Objektorientierte Programmierung der PHP-Journey von Coddy. Lektion 36 von 91.
Wenn du self:: in einer übergeordneten Klasse verwendest, bezieht es sich immer auf die Klasse, in der es geschrieben wurde, nicht auf die Klasse, die tatsächlich verwendet wird. Dies kann zu unerwartetem Verhalten bei der Vererbung führen. Spätes statisches Binden löst dieses Problem mithilfe des Schlüsselworts static::.
Betrachte dieses Beispiel, in dem self:: nicht wie erwartet funktioniert:
<?php
class ParentClass {
public static function create() {
return new self();
}
public static function getClassName() {
return self::class;
}
}
class ChildClass extends ParentClass {}
$obj = ChildClass::create();
echo get_class($obj) . "\n";
echo ChildClass::getClassName();
Ausgabe:
ParentClass
ParentClassObwohl wir ChildClass::create() aufgerufen haben, erhielten wir ein ParentClass-Objekt, weil self:: zur Kompilierungszeit aufgelöst wird. Verwenden wir nun stattdessen static:::
<?php
class ParentClass {
public static function create() {
return new static();
}
public static function getClassName() {
return static::class;
}
}
class ChildClass extends ParentClass {}
$obj = ChildClass::create();
echo get_class($obj) . "\n";
echo ChildClass::getClassName();
Ausgabe:
ChildClass
ChildClassMit static:: wartet PHP bis zur Laufzeit, um zu bestimmen, welche Klasse verwendet werden soll. Dies wird als „spätes“ Binden bezeichnet, weil die Entscheidung verzögert wird. Es ist unverzichtbar für Factory-Methoden und jede statische Methode, die Vererbung berücksichtigen soll.
Wichtiger Punkt: Verwende static:: statt self::, wenn du möchtest, dass Kindklassen statisches Verhalten korrekt erben und anpassen.
Aufgabe
EinfachLass uns ein Modellregistrierungssystem erstellen, das die Leistungsfähigkeit der späten statischen Bindung demonstriert. Du erstellst eine übergeordnete Model-Klasse mit einer Factory-Methode, die untergeordnete Klassen erben können. Dank static:: wird jede untergeordnete Klasse korrekt Instanzen ihrer selbst statt der übergeordneten Klasse erstellen.
Du wirst deinen Code auf vier Dateien verteilen:
Model.php: Erstelle eine übergeordneteModel-Klasse mit einer geschützten statischen Eigenschaft$tableName, die auf"models"gesetzt ist. Füge eine statische Methodecreate()hinzu, dienew static()verwendet, um eine neue Instanz der Klasse zurückzugeben, von der sie aufgerufen wurde. Füge außerdem eine statische MethodegetTable()hinzu, diestatic::$tableNamezurückgibt. Füge schließlich einedescribe()-Methode hinzu, die mithilfe vonstatic::classundstatic::$tableName"[ClassName] from table [tableName]"zurückgibt.User.php: Erstelle eineUser-Klasse, dieModelerweitert. Binde die übergeordnete Datei ein. Überschreibe die statische Eigenschaft$tableNamemit"users". Die Klasse erbt alle Methoden vonModel, ohne Änderungen vorzunehmen.Product.php: Erstelle eineProduct-Klasse, dieModelerweitert. Binde die übergeordnete Datei ein. Überschreibe die statische Eigenschaft$tableNamemit"products". Auch diese Klasse erbt alle Methoden von der übergeordneten Klasse.main.php: Binde sowohl die User- als auch die Product-Datei ein. Verwende die geerbte Factory-Methodecreate(), um Instanzen vonUserundProductzu erstellen. Rufe für jede Instanzdescribe()auf und gib das Ergebnis in einer eigenen Zeile aus. Gib anschließend den Tabellennamen für jede Klasse mithilfe vonUser::getTable()undProduct::getTable()aus, jeweils in einer eigenen Zeile.
Der entscheidende Punkt ist, dass die Methoden create() und getTable() nur in der übergeordneten Model-Klasse definiert sind und dennoch korrekt mit den untergeordneten Klassen funktionieren, weil static:: die Bindung bis zur Laufzeit verzögert. Wenn du User::create() aufrufst, erstellt PHP eine User-Instanz und keine Model-Instanz, da sich static:: auf die Klasse bezieht, die tatsächlich aufgerufen wurde.
Deine Ausgabe sollte vier Zeilen enthalten: die Beschreibung der User-Instanz, die Beschreibung der Product-Instanz, den User-Tabellennamen und den Product-Tabellennamen.
Probier es selbst
<?php
require_once 'User.php';
require_once 'Product.php';
// TODO: Verwende die geerbte create()-Factory-Methode, um eine User-Instanz zu erstellen
// TODO: Verwende die geerbte create()-Factory-Methode, um eine Product-Instanz zu erstellen
// TODO: Rufe describe() auf der User-Instanz auf und gib das Ergebnis aus
// TODO: Rufe describe() auf der Product-Instanz auf und gib das Ergebnis aus
// TODO: Gib User::getTable() aus
// TODO: Gib Product::getTable() aus
?>Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienEinführung in OOPKlassen vs. ObjekteDas Schlüsselwort $thisMethodenEigenschaftenKonstruktor (__construct)Destruktor (__destruct)Rückblick – Einfacher Taschenrechner4Vererbung
Grundlegende VererbungDas Schlüsselwort parent::MethodenüberschreibungDas Schlüsselwort finalAbstrakte KlassenRückblick – Mitarbeiterhierarchie7Kapselung
Öffentlich, geschützt, privatZugriffsmodifikatoren im DetailGetter und SetterInformationsverbergungKonstruktor-Promotion (8.0)Wiederholung – System zur Verwaltung von Schülerdatensätzen2Namespaces & Autoloading
Einführung in NamespacesDas use-SchlüsselwortPSR-4-Autoloading-StandardComposer-AutoloaderRückblick – Organisiertes Projekt5Schnittstellen & Verträge
Einführung in SchnittstellenSchnittstellen implementierenMehrere Schnittstellen implementierenSchnittstelle vs. abstrakte KlasseTyp-Hinweise mit SchnittstellenRückblick – Formrechner8Magische Methoden
Einführung in magische Methoden__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Objektklonen__serialize & __unserializeRückblick – Benutzerdefinierte Sammlung11Typsystem & Fehlerbehandlung
TypdeklarationenNullable-TypenUnion- & Intersection-TypenException-KlassenBenutzerdefinierte Exception-HierarchieTry, Catch, FinallyRückblick – Formularvalidator14Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und Benutzerklassen3Klassen-Eigenschaften
Instanz- vs. statische EigenschaftenKonstanten in KlassenStatische Methoden & EigenschaftenPrivate & geschützte EigenschaftenSchreibgeschützte Eigenschaften (PHP 8.1)Zusammenfassung – Bankkonto-Manager6Polymorphie
Methodenüberschreibung erneut betrachtetPolymorphie über SchnittstellenTyp-Hinweise & Union-TypenSpätes statisches BindenRückblick – Zahlungsabwickler9Traits
Einführung in TraitsMehrere Traits verwendenAuflösung von Trait-KonfliktenAbstrakte Methoden in TraitsTraits vs. Vererbung12Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFactory-MusterObserver-MusterStrategy-Muster15Abschließende Herausforderungen
E-Learning-PlattformBankingsystemEntwicklung einer SpielfigurFahrzeugvermietungÜbe selbstständig: Online-PHP-Compiler