2010-10-31 6 views
2

J'ai récemment posé quelques questions sur ce sujet, donc je pense qu'il convient de lier les questions associées.Objets PHP et fermetures

PHP closures and implicit global variable scope

J'ai un ensemble de classes qui utilisent des fermetures comme dans l'exemple ci-dessous (gardez à l'esprit je me suis vite ensemble des coups de poing cet exemple pour ce fil) Ma question consiste à faire passer l'argument $obj aux fonctions.

-t-il existe une sorte de magie variables (cough- $this -cough) qui me permettrait d'accéder à l'objet où il est appelé, au lieu d'avoir besoin de déclarer un argument fictif de $obj ou quoi? Peut-être que j'ai mal lu, mais il semble que la fonctionnalité que je cherche a été supprimée, au moins dans le contexte de $this.

class Test{ 

    private $_color; 
    protected $_children = array(); 

    public function __construct(Closure $function){ 
     $function($this); 
    } 

    public function create(Closure $function){ 
     return new self($function); 
    } 

    public function color($color){ 
     $this->_color = $color; 
     return $this; 
    } 

    public function add(Closure $function){ 
     $this->_children[] = new Test($function); 
     return $this; 
    } 

} 

Test::create(function($obj){ 
    $obj->color('Red') 
     ->add(function(){ 
      $obj->color('Green'); 
     }) 
     ->color('Blue'); 
    }); 

La seule alternative que je peux voir hors main stocke une instance de chaque objet à la création, et en fournissant une fonction pour renvoyer cette instance comme suit:

class Test{ 

    private $_color; 
    private static $_instance; 
    protected $_children = array(); 

    public function __construct(Closure $function){ 
     self::$_instance = $this; 
     $function(); 
    } 

    . 
    . 
    . 

    public static function this(){ 
     return self::$_instance; 
    } 

} 

Test::create(function(){ 
    Test::this() 
     ->color('Red') 
     ->add(function(){ 
      Test::this() 
       ->color('Green'); 
     }) 
     ->color('Blue'); 
    }); 

Répondre

1

Vous devez utiliser la première version . Fournir l'instance de classe de manière statique n'est pas vraiment bon (à part l'utilisation de singleton.) Imaginez que vous ayez deux instances. Alors seulement ce dernier sera servi statiquement. Vous ne pouviez rien faire avec le premier. Même avec votre première approche, il existe une limitation non négligeable: vous ne pouvez accéder qu'aux méthodes publiques. Il existe une solution de contournement hacky utilisant Reflection autour de cela. Alors, n'utilisez-vous que des méthodes publiques?

À un moment donné, Closure était considéré comme un détail d'implémentation et ne devait pas être utilisé. Ce n'est plus le cas; Closure est le type documenté de fonctions anonymes.

+0

Merci ** nikic **; Seules les méthodes publiques sont appelées, donc la visibilité n'est pas un problème. Je suis conscient du manque de fiabilité de la classe 'Closure', et je vais revenir à quelque chose de plus permanent quand le moment viendra, j'aime juste le type-hinting qu'il fournit dans l'IDE que j'utilise. Peu importe, il n'y a pas de variables * magic *, ou d'autres astuces que je pourrais utiliser pour réaliser cette fonctionnalité intrinsèquement? – Dan

+1

Non, il n'y en a pas;) – NikiC

+0

Merci encore ** nikic ** :) – Dan