Late Static Bindings (Résolution statique à la volée)
PHP implémente une fonctionnalité appelée
late static binding, en français la résolution
statique Ă la volĂ©e, qui peut ĂȘtre utilisĂ©e pour rĂ©fĂ©rencer la classe appelĂ©e
dans le contexte de l'héritage statique.
Plus précisément, les résolutions statiques à la volée fonctionnent en enregistrant
le nom de la classe dans le dernier "appel non transmis". Dans le cas des appels de
mĂ©thodes statiques, il s'agit de la classe explicitement nommĂ©e (gĂ©nĂ©ralement, celle Ă
gauche de l'opérateur
::) ;
dans le cas de méthodes non statiques, il s'agit de la classe de l'objet. Un "appel
transmis" est un appel statique déclenché par self::,
parent::, static::, ou, tout en haut de la
hiérarchie des classes, forward_static_call().
La fonction get_called_class() peut ĂȘtre utilisĂ©e pour rĂ©cupĂ©rer
une chaßne contenant le nom de la classe appelée, et static::
introduit sa portée.
Cette fonctionnalité a été baptisée "late static bindings",
avec un point de vue interne. "Late binding", littéralement
résolution tardive, vient du fait que les éléments static::
ne seront pas rĂ©solus en utilisant la classe oĂč la mĂ©thode a Ă©tĂ© dĂ©finie, mais
celle qui est active durant l'exécution. L'adjectif statique a été
ajoutĂ© car ce problĂšme s'applique (sans y ĂȘtre limitĂ©) aux mĂ©thodes statiques.
Limitations de self::
Les références statiques à la classe courante, avec self:: ou
__CLASS__, sont résolues en utilisant la classe à laquelle
appartiennent les fonctions, celle oĂč elles ont Ă©tĂ© dĂ©finies :
Exemple #1 Utilisation de self::
<?php
class A
{
public static function qui()
{
echo __CLASS__;
}
public static function test()
{
self::qui();
}
}
class B extends A
{
public static function qui()
{
echo __CLASS__;
}
}
B::test();
?>
L'exemple ci-dessus va afficher :
Utilisation de la résolution statique à la volée
La résolution statique à la volée essaie de dépasser cette limitation
en introduisant un mot clé qui fait référence à la classe
qui a été appelée durant l'exécution. Pour faire simple, ce mot-clé
permet le référencement à B depuis
test(), dans l'exemple précédent.
Il a été décidé de ne pas introduire de nouveau mot clé, mais
plutĂŽt d'utiliser le mot static qui Ă©tait dĂ©jĂ
réservé.
Exemple #2 Utilisation simple de static::
<?php
class A
{
public static function qui()
{
echo __CLASS__;
}
public static function test()
{
static::qui(); // Ici, résolution à la volée
}
}
class B extends A
{
public static function qui()
{
echo __CLASS__;
}
}
B::test();
?>
L'exemple ci-dessus va afficher :
Note:
Dans les contextes non statiques, la classe appelée sera celle de l'objet.
Comme $this-> essayera d'appeler
des mĂ©thodes privĂ©es depuis le mĂȘme contexte, utiliser static::
pourrait donner des résultats différents. Une autre différence est que
static:: ne peut faire référence qu'à des propriétés
statiques.
Exemple #3 Utilisation de static:: dans un contexte non statique
<?php
class A
{
private function foo()
{
echo "Success!\n";
}
public function test()
{
$this->foo();
static::foo();
}
}
class B extends A
{
/* foo() sera copiée dans B, par conséquent son contexte sera toujours A
* et l'appel se fera sans problĂšme */
}
class C extends A
{
private function foo()
{
/* La méthode originale est remplacée; le contexte est celui de C */
}
}
$b = new B();
$b->test();
$c = new C();
try {
$c->test();
} catch (Error $e) {
echo $e->getMessage();
}
?>
L'exemple ci-dessus va afficher :
Success!
Success!
Success!
Call to private method C::foo() from scope A
Note:
La rĂ©solution des statiques Ă la volĂ©e va s'arrĂȘter Ă un appel statique
complÚtement résolu. D'un autre cÎté, les appels statiques en utilisant
un mot-clé comme parent:: ou self::
vont transmettre l'information appelante.
Exemple #4 Appel avec ou sans transmission
<?php
class A
{
public static function foo()
{
static::qui();
}
public static function qui()
{
echo __CLASS__."\n";
}
}
class B extends A
{
public static function test()
{
A::foo();
parent::foo();
self::foo();
}
public static function qui()
{
echo __CLASS__."\n";
}
}
class C extends B
{
public static function qui()
{
echo __CLASS__."\n";
}
}
C::test();
?>
L'exemple ci-dessus va afficher :