Réponses:
Vous devez absolument lire les liaisons statiques tardives dans le manuel PHP. Cependant, je vais essayer de vous donner un bref résumé.
En gros, cela se résume au fait que le self
mot-clé ne suit pas les mêmes règles d'héritage. self
résout toujours la classe dans laquelle il est utilisé. Cela signifie que si vous créez une méthode dans une classe parent et que vous l'appelez à partir d'une classe enfant, vous self
ne référencerez pas l'enfant comme vous vous en doutez.
La liaison statique tardive introduit une nouvelle utilisation du static
mot - clé, qui résout cette lacune particulière. Lorsque vous utilisez static
, il représente la classe où vous l'utilisez pour la première fois, c'est-à-dire. il «se lie» à la classe d'exécution.
Ce sont les deux concepts de base derrière cela. La façon self
, parent
et static
fonctionne quand static
est en jeu peut être subtile, alors plutôt que d' aller pour plus de détails, je vous recommande fortement que vous étudiez les exemples de pages de manuel. Une fois que vous avez compris les bases de chaque mot-clé, les exemples sont tout à fait nécessaires pour voir le type de résultats que vous allez obtenir.
self
mot-clé ne suit pas les règles d'héritage. self
résout toujours la classe dans laquelle il est utilisé." - Ce qui ne signifie pas que vous ne pouvez pas appeler la méthode statique d'un parent à partir d'un objet enfant via self
, comme avec les méthodes non statiques. Vous pensez peut-être la bonne chose, mais vous devriez reformuler cela. Tout cela n'a vraiment d'importance qu'une fois que les enfants ont des membres nommés de manière identique, car vous pouvez ensuite décider à ceux auxquels vous référer en utilisant à la static::
place.
Depuis PHP: liaisons statiques tardives - Manuel :
Depuis PHP 5.3.0, PHP implémente une fonctionnalité appelée liaison statique tardive qui peut être utilisée pour référencer la classe appelée dans le contexte de l'héritage statique.
La liaison statique tardive tente de résoudre cette limitation en introduisant un mot-clé qui fait référence à la classe initialement appelée au moment de l'exécution. ... Il a été décidé de ne pas introduire de nouveau mot-clé, mais plutôt d'utiliser
static
qui était déjà réservé.
Voyons un exemple:
<?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
?>
Les liaisons statiques tardives fonctionnent en stockant la classe nommée dans le dernier "appel sans transfert". En cas d'appels de méthodes statiques, il s'agit de la classe explicitement nommée (généralement celle à gauche de l'
::
opérateur); en cas d'appels de méthode non statiques, c'est la classe de l'objet. Un « appel de transfert » est une statique qui est introduit parself::
,parent::
,static::
ou, si vous allez dans la hiérarchie des classes,forward_static_call()
. La fonctionget_called_class()
peut être utilisée pour récupérer une chaîne avec le nom de la classe appelée etstatic::
introduit sa portée.
Il n'y a pas de comportement très évident:
Le code suivant produit «alphabeta».
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
Cependant, si nous supprimons la déclaration de la fonction classname de la classe beta, nous obtenons 'alphaalpha' comme résultat.
Je cite le livre: "PHP Master écrit du code de pointe".
La liaison statique tardive était une fonctionnalité introduite avec php 5.3. Cela nous permet d'hériter des méthodes statiques d'une classe parent et de référencer la classe enfant appelée.
Cela signifie que vous pouvez avoir une classe abstraite avec des méthodes statiques et référencer les implémentations concrètes de la classe enfant en utilisant la notation static :: method () au lieu de self :: method ().
N'hésitez pas à consulter également la documentation officielle de php: http://php.net/manual/en/language.oop5.late-static-bindings.php
La manière la plus claire d'expliquer la liaison statique tardive est d'utiliser un exemple simple. Jetez un œil aux deux définitions de classe ci-dessous et poursuivez votre lecture.
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";
}
}
Nous voyons une classe parent (véhicule) et une classe enfant (voiture). La classe parent a 2 méthodes publiques:
invokeDriveByStatic
invokeStopBySelf
La classe parent dispose également de 2 méthodes privées:
drive
stop
La classe enfant remplace 2 méthodes:
drive
stop
Appelons maintenant les méthodes publiques:
invokeDriveByStatic
invokeStopBySelf
Demandez-vous: quelle classe invoque invokeDriveByStatic
/ invokeStopBySelf
? La classe Parent ou Enfant?
Jetez un œil ci-dessous:
// 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
Le static
mot-clé est utilisé dans un modèle de conception Singleton. Voir le lien: https://refactoring.guru/design-patterns/singleton/php/example
L'exemple le plus simple pour montrer la différence.
Remarque, soi - même :: $ c
class A
{
static $c = 7;
public static function getVal()
{
return self::$c;
}
}
class B extends A
{
static $c = 8;
}
B::getVal(); // 7
Liaison statique tardive, notez static :: $ c
class A
{
static $c = 7;
public static function getVal()
{
return static::$c;
}
}
class B extends A
{
static $c = 8;
}
B::getVal(); // 8
En le regardant à partir d'un "pourquoi est-ce que j'utiliserais ceci?" perspective, c'est essentiellement un moyen de changer le contexte à partir duquel la méthode statique est interprétée / exécutée.
Avec self
, le contexte est celui dans lequel vous avez défini la méthode à l'origine. Avec static
, c'est celui d'où vous l'appelez.
Vérifiez également si vous mettez à jour des variables statiques dans les classes enfants. J'ai trouvé ce résultat (quelque peu) inattendu où l'enfant B met à jour l'enfant 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
// )
Vous pouvez le corriger en déclarant la même variable dans chaque classe enfant, par exemple:
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;
}
}