La résolution statique à la volée ou Late Static Bindings

La résolution tardive pour renforcer le principe d'héritage

14 octobre 2012

Depuis PHP 5.3, le langage implémente une fonctionnalité nommée "résolution statique à la volée" ou en anglais "late static bindings". Cette fonctionnalité permet de mieux résoudre les appels des méthodes statiques.

Pour mieux comprendre, voici un exemple : je possède une bibliothèque de jeux (échecs, dames, petits chevaux etc...) qui ont tous un plateau. Naturellement je ne souhaite pas ré-implémenter dans toutes mes classes les parties de code qui peuvent être en commun, j'aurai donc une classe mère Plateau dont hériteront tous mes plateaux. Un plateau de jeu est quelque chose d'unique dans une partie, il serait fort dommage de créer un deuxième plateau en pleine partie d'échecs. Tous mes plateaux seront donc des Singleton.

Sans le late static bindings, l'erreur courante

Utilisation de get_class, __CLASS__ ou self

class Plateau
{
	protected static $_oInstance = null;

	protected function __construct()
	{
		echo "Je suis la classe mere.";
	}
	
	public static function getInstance()
	{
		// Faites votre choix entre
		return (self::$_oInstance ?: (self::$_oInstance = new self));
		
		// OU
		$sClasseNom = __CLASS__;
		return (self::$_oInstance ?: (self::$_oInstance = new $sClasseNom));
		
		// OU
		$sClasseNom = get_class();
		return (self::$_oInstance ?: (self::$_oInstance = new $sClasseNom));
	}
}

class PlateauEchec extends Plateau
{
	protected function __construct()
	{
		echo "Je suis le plateau d'echec.";
	}
}

$plateau = PlateauEchec::getInstance();
/* Affichage : Je suis la classe mere. */

echo get_class($plateau);
/* Affichage : Plateau */
	

Et oui ! Lors de la résolution, PHP a instancié la mauvaise classe. En pratique la classe Plateau devrait même être déclarée abstraite, ce qui nous aurait valu une jolie erreur.

Avec le late static bindings

Utilisation de get_called_class ou static

class Plateau
{
	protected static $_oInstance = null;

	protected function __construct()
	{
		echo "Je suis la classe mere.";
	}
	
	public static function getInstance()
	{
		// Faites votre choix entre
		return (self::$_oInstance ?: (self::$_oInstance = new static));
				
		// OU
		$sClasseNom = get_called_class();
		return (self::$_oInstance ?: (self::$_oInstance = new $sClasseNom));
	}
}

class PlateauEchec extends Plateau
{
	protected function __construct()
	{
		echo "Je suis le plateau d'echec.";
	}
}

$plateau = PlateauEchec::getInstance();
/* Affichage : Je suis le plateau d'echec. */

echo get_class($plateau);
/* Affichage : PlateauEchec */
	

Champion !

Le mot clé static permet, dans cette situation, de résoudre la classe appelante lors de l'exécution. Malgré son nom, le Late Static Bindings n'est pas un phénomène réservé aux méthodes déclarée statiques, j'ai eu pour ma part, par exemple, quelques surprises en utilisant la réflexivité. Mais ceci fera l'objet d'un prochain tutoriel.

A bientôt !

Par
Créateur et administrateur.

Dans la même catégorie

Formater un tableau pour CURLOPT_POSTFIELDS
Email avec pièce jointe en PHP
PHP : modifier les attributs privés d'un objet
Tester l'existence d'un fichier dans l'include path
Convertir récursivement un objet PHP en tableau
PHP : formater un tableau en CSV
Comment envoyer un mail en ligne de commande ?
RSYNC : Comment synchroniser des fichiers à travers une connexion ssh ?
Exécuter un code PHP en ligne de commande
Doctrine 2 : générer les classes PHP depuis la base de données
Comment catcher les erreurs en PHP ?
Doctrine 2 : comment afficher la requête SQL ?
Comment construire une URL sans caractères spéciaux en PHP ?
Comment lister les fichiers PHP inclus sur ma page ?
Les fonctions anonymes récursives en PHP
Requête HTTP asynchrone en PHP
Trouver les jours fériés français en PHP
Comment allumer son ordinateur à distance en PHP ?
Comment utiliser la balise meta viewport ?
Une version mobile de mon site avec le Zend Framework
Doctrine et le Zend Framework : Présentation, intégration et utilisation
Créer son flux RSS simplement avec Zend_Feed
Appliquer un layout sur un mail avec le Zend Framework
Comment lancer une requête multi-bases avec les fonctions MySQL ?
Implode / Explode : Du tableau à la chaine de caractères, de la chaine de caractères au tableau

Commentaire(s)