Simuler la visibilité package (comme en java)

Contenu du snippet

Alors voilà ... Je me demandais commment on pouvait faire en PHP pour interdire à l'utilisateur de créer lui-même une nouvelle instance de classe, mais par contre rendre cette création possible lors d'un appel à une méthode.
Un exemple concrêt permet de mieux cerner le problème : imaginons une classe qui modélise un noeud XML. Chaque instance de cette classe va posséder une référence vers un objet parent. Et l'objet parent va également posséder une référence vers l'objet fils.
L'idéal serait alors de faire :
$child = new Node();
$child -> setParent($parent);
$parent -> addChild($child);
Cette procédure est parfaite et ne pose aucun problème si l'utilisateur la respecte bien. Mais si un jour il utilise seulement $child = new Node() ... Bah ça ne correspond plus à rien.
Il faudrait plutôt utiliser une méthode de la classe Node qui permet d'automatiser la création de fils :
$child = $parent -> getEmptyChild();
Et empêcher la création d'un nouveau noeud autrement qu'à travers cette méthode ...
C'est la que ma visibilité intervient ...

Source / Exemple :


<?php
/* -------------------- */
	class MyOwnClass
	{
		private $Friends = array();
		
		private function addFriend($name)
		{
			$friends = &$this -> Friends;
			array_push($friends, $name);
		}
		
		public function __construct()
		{
			$this -> addFriend('MyFriendClass');
		}
		
		private function isCalledByFriend()
		{
			$stack = debug_backtrace();
			$stack = array_slice($stack, 2, count($stack) - 2);
			
			$friends = &$this -> Friends;
			
			$friend = false;
			foreach($stack as $call)
			{
				if(in_array($call['class'], $friends)) 
				{
					$friend = true;
					break;
				}
			}
			
			return $friend;
		}
		
		public function methodCalledOnlyByFriends()
		{
			if(!$this -> isCalledByFriend()) throw new Exception('Impossible d\'appeller cette méthode. ');
		}
	
	}
/* -------------------- */
	class MyFriendClass
	{
		public function __construct()
		{
		
		}
		
		public function callMethodOfFriend()
		{
			$instance = new MyOwnClass();
			$instance -> methodCalledOnlyByFriends();
		}
	
	}
/* -------------------- */
	$instance = new MyFriendClass();
	$instance -> callMethodOfFriend();
/* -------------------- */
?>

Conclusion :


La manière de procéder est plutôt ... Sale. On récupère la pile des appels pour vérifier que la méthode appellée a bien été appellée par une classe qui se trouve dans la liste des classes dites "amies".
On pourrait améliorer le code en définissant toutes les classes amies comme celles qui se trouvent dans le même répertoire que la classe en question. Qui sait ?
C'est un code un peu experimental et je le mets en initié non-pas parce qu'il est compliqué d'un point-de-vue langage, mais plutôt d'un point-de-vue compréhension.

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.