2009-08-19 5 views
0

Je me demande s'il est possible d'encapsuler les méthodes d'une classe, mais de les exposer ensuite dans une classe consommatrice. Par exemple (JFTR, je sais que ce code est erroné)Méthodes d'encapsulation et d'héritage

class Consumer{ 
     public function __construct($obj){ 
      $this->obj = $obj; 
      } 

     public function doCommand(){ 
      $this->obj->command(); 
      } 
     } 

    class Consumed{ 
     //I would make the constructor private, but to save space... 
     public function __construct(){} 
     private function command(){ 
      echo "Executing command in the context of the Consumer"; 
      } 
     } 

    $consumer = new Consumer(new Consumed); 
    $consumer->doCommand(); 

    //just to reiterate, I know this throws an error 

En fin de compte, je veux être en mesure de fabriquer des composants qui ne peuvent être référencés directement en dehors du contexte d'une seule classe de contrôle.

+0

Vous voulez dire quelque chose comme une classe d'amis en C++? http://en.wikipedia.org/wiki/Friend_class – VolkerK

+0

Vous ne pouvez pas l'avoir dans les deux sens, si vous cachez des fonctionnalités dans la méthode privée, alors il ne peut pas être appelé de l'extérieur. Si vous l'exposer de quelque façon que ce soit (en faisant une méthode publique, qui à son tour appelle la méthode privée), tout le monde peut invoquer votre méthode privée. –

+0

Le commentaire ci-dessus est sur PHP bien sûr :) la classe d'amis fonctionnerait, mais il n'y a pas un tel concept en PHP. –

Répondre

0

Bien sûr, il peut, juste faire ces méthodes protected, pas private et ont Consumed étendent à partir Consumer. Cependant, je ne suis pas sûr des avantages.

+0

pour empêcher l'accès direct à leurs méthodes et forcer un seul point d'entrée. Est-ce mal du point de vue du design? – sunwukung

+0

Peut-être. Je veux dire, cette classe «consommée» est fondamentalement impossible à tester. Quel serait le but d'une classe sans interface publique? C'est peut-être un signe que vous n'avez pas vraiment besoin de cette classe. Les restrictions d'accès ne garantissent pas nécessairement un bon design. Quel est le ** problème ** que vous essayez de résoudre? –

+0

aucun vraiment - j'étudie juste le sujet. Je roule mon propre MVC dans le cadre de ce processus (redondant, je sais, mais un exercice intellectuel pour m'aider à apprendre). Dans ma couche de présentation, il y a une classe d'objet utilisée par le contrôleur de vue pour servir des modèles partiels dans un maître, et je veux empêcher cet objet d'être accédé directement. J'y ai réfléchi après avoir regardé le schéma stratégie/commande - dans les exemples que j'ai vus, les composants consommés pouvaient simplement être accédés directement - et il semblait que le point d'entrée unique était juste honoré comme point de principe. – sunwukung

1

Vous pouvez émuler quelque chose de similaire avec __call et debug_backtrace.

<?php 
class Consumer{ 
    public function __construct($obj){ 
    $this->obj = $obj; 
    } 

    public function doCommand(){ 
    $this->obj->command(); 
    } 
} 

class Consumed { 
    // classes that are aloowed to call private functions 
    private $friends = array('Consumer'); 

    public function __construct(){} 
    private function command() { 
    echo "Executing command in the context of the Consumer. \n"; 
    } 

    public function __call($name, $arguments) { 
    $dt = debug_backtrace(); 
    // [0] describes this method's frame 
    // [1] is the would-be frame of the method command() 
    // [2] is the frame of the direct caller. That's the interesting one. 
    if (isset($dt[2], $dt[2]['class']) && in_array($dt[2]['class'], $this->friends)) { 
     return call_user_func_array(array($this,$name), $arguments); 
    } 
    else { 
     die('!__call()'); 
    } 
    } 
} 

$c = new Consumed; 
$consumer = new Consumer($c); 
$consumer->doCommand(); 

echo 'and now without Consumer: '; 
$c->command(); 

impressions

Executing command in the context of the Consumer. 
and now without Consumer: !__call() 
Questions connexes