Définition et intérêt de la résolution statique à la volée
La résolution statique à la volée va nous permettre de faire référence à la classe réellement appelée dans un contexte d’héritage statique.
En effet, lorsqu’on utilise le self::
pour faire référence à la classe courante dans un contexte statique, la classe utilisée sera toujours celle dans laquelle sont définies les méthodes utilisant self::
.
Cela peut parfois produire des comportements inattendus. Regardez plutôt l’exemple ci-dessous pour vous en convaincre.
<?php abstract class Utilisateur{ protected $user_name; protected $user_region; protected $prix_abo; protected $user_pass; protected $x = 0; public const ABONNEMENT = 15; public function __construct($n, $p, $r){ $this->user_name = $n; $this->user_pass = $p; $this->user_region = $r; } public function __destruct(){ //Du code à exécuter } public static function getStatut(){ self::statut(); } public static function statut(){ echo 'Utilisateur'; } public function getNom(){ echo $this->user_name; } public function getPrixAbo(){ echo $this->prix_abo; } abstract public function setPrixAbo(); } ?>
<?php class Admin extends Utilisateur{ protected static $ban; public function __construct($n, $p, $r){ $this->user_name = strtoupper($n); $this->user_pass = $p; $this->user_region = $r; } public static function statut(){ echo 'Admin'; } public function getNom(){ echo $this->user_name. '(Admin)'; } public function setBan(...$b){ foreach($b as $banned){ self::$ban[] .= $banned; } } public function getBan(){ echo 'Utilisateurs bannis : '; foreach(self::$ban as $valeur){ echo $valeur .', '; } } public function setPrixAbo(){ if($this->user_region === 'Sud'){ return $this->prix_abo = parent::ABONNEMENT / 6; }else{ return $this->prix_abo = parent::ABONNEMENT / 3; } } } ?>
<!DOCTYPE html> <html> <head> <title>Cours PHP & MySQL</title> <meta charset="utf-8"> <link rel="stylesheet" href="cours.css"> </head> <body> <h1>Titre principal</h1> <?php spl_autoload_register(function($classe){ require 'classes/' .$classe. '.class.php'; }); /*On n'a pas besoin d'instancier nos classes ici puisqu'on se contente *d'utiliser une méthode statique (= qui appartient à la classe)*/ Admin::getStatut(); ?> <p>Un paragraphe</p> </body> </html>
Ici, on réutilise nos classes Utilisateur
(classe mère) et Admin
(classe étendue). Dans notre classe Utilisateur
, on définit deux méthodes statiques getStatut()
et statut()
.
La méthode statut()
de la classe Utilisateur
renvoie le mot « Utilisateur ». La méthode getStatut()
sert elle a exécuter la méthode statut()
de la classe courante.
On surcharge ensuite notre méthode statut()
dans notre classe étendue Admin
afin qu’elle renvoie le texte « Admin ».
Finalement, dans notre script principal, on appelle notre méthode getStatut()
depuis notre classe Admin
.
Comme vous pouvez le voir, le résultat renvoyé est « Utilisateur » et non pas « Admin » comme on aurait pu le penser instinctivement. Cela est dû au fait que le code self::
dans notre méthode getStatut()
va toujours faire référence à la classe dans laquelle la méthode a été définie, c’est-à-dire la classe Utilisateur
.
Ainsi, self::statut()
sera toujours l’équivalent de Utilisateur::statut()
et renverra toujours la valeur de la méthode statut()
définie dans la classe Utilisateur
.
La résolution statique à la volée a été introduite justement pour dépasser ce problème précis et pour pouvoir faire référence à la classe réellement utilisée.
Utilisation de la résolution statique à la volée et de static::
La résolution statique à la volée va donc nous permettre de faire référence à la classe réellement utilisée dans un contexte statique.
Pour utiliser la résolution statique à la volée, nous allons simplement devoir utiliser le mot clef static
à la place de self
. Ce mot clef va nous permettre de faire référence à la classe utilisée durant l’exécution de notre méthode.
Reprenons l’exemple précédent et changeons self::
par static::
dans le code de notre méthode getStatut()
.
<?php abstract class Utilisateur{ protected $user_name; protected $user_region; protected $prix_abo; protected $user_pass; protected $x = 0; public const ABONNEMENT = 15; public function __construct($n, $p, $r){ $this->user_name = $n; $this->user_pass = $p; $this->user_region = $r; } public function __destruct(){ //Du code à exécuter } public static function getStatut(){ static::statut(); } public static function statut(){ echo 'Utilisateur'; } public function getNom(){ echo $this->user_name; } public function getPrixAbo(){ echo $this->prix_abo; } abstract public function setPrixAbo(); } ?>
Cette fois-ci, la méthode getStatut()
va exécuter la méthode statut()
de la classe utilisée, c’est-à-dire de la classe Admin
et c’est donc la valeur « Admin » qui va être renvoyée.