2010-09-23 2 views
1

J'ai une classe qui contient un tableau d'objets et a des méthodes pour renvoyer un objet de ce tableau par référence. Il existe également une méthode pour supprimer un objet du tableau.Désactiver la variable à la référence dans php

Cependant, si j'ai une variable qui fait référence à un objet du tableau, et que cet élément n'est pas défini, la variable a toujours une référence. Que dois-je faire dans la méthode remove qui détruira définitivement cet objet, y compris les références à celui-ci.

class myClass 
{ 
    public $objectList = array(); 

    public function __construct() 
    { 
     $objectList[] = new myObject(); 
    } 

    public function &getObjectByReference() 
    { 
     return $this->objectList[0]; 
    } 

    public function removeObject() 
    { 
     unset($this->objectList[0]); 
    } 
} 
$myClass = new myClass(); 
$referencedObject = $myClass->getObjectByReference(); 
// this can now use the methods from myObject 
$myClass-> removeObject(); 
// supposed to delete the object from memory. However $referencedObject is still 
// able to use all the methods from myObject. 

donc c'est le problème que j'ai, je dois être en mesure de retirer du tableau et supprimer l'objet de la mémoire si les variables qui font référence à cet objet ne sont plus utilisables.

Répondre

0

Avez-vous essayé de faire:

$referencedObject = &$myClass->getObjectByReference(); 

est $ referencedObject toujours là après avoir mis dans ce &?

0

Pour créer une référence à partir d'une valeur de retour, la fonction doit renvoyer par référence (vous le faites déjà) et l'affectation doit par référence. Donc, vous devriez écrire:

$referencedObject =& $myClass->getObjectByReference(); 

Si vous faites cela, la référence sera vraiment détruite.

Mais si vous voulez détruire toutes les variables ayant cet objet comme valeur (et qui sont et non références) alors ceci est impossible. Vous ne pouvez supprimer que les vraies références, pas les variables ayant la même valeur;)

+0

J'ai essayé de le faire de cette façon, mais lorsque j'appelle print_r ($ referencedObject), il affiche toujours toutes ses variables membres pour qu'il ne puisse pas disparaître? – wiggles

0

Php travaille avec garbage collector: s'il existe encore une référence à l'objet, alors l'objet n'est pas supprimé.

unset($this->objectList[0]) 

ne supprime pas l'objet, mais la valeur de $ this-> ObjectList, l'objet existe encore car il est référencé par $ referencedObject.

Une solution: lorsque vous supprimez l'objet, dites-lui qu'il est supprimé et dans cet objet vous avez un booléen "isDeleted". Ensuite, pour chaque méthode de cet objet, vérifiez si isDeleted est vrai et dans ce cas, ne faites rien.

+0

Un joli petit travail autour, je n'avais pas pensé à ça :) – wiggles

0

C'est la nature du garbage collector de PHP. Pour vous assurer qu'un interlocuteur ne conserve pas de référence à votre objet, vous devez vous assurer qu'il ne peut jamais toucher l'objet d'origine. Voici une idée:

class myClass 
{ 
    public $objectList = array(); 

    public function __construct() 
    { 
     $objectList[] = new Wrapper(new myObject()); 
    } 

    public function getObject() 
    { 
     return $this->objectList[0]; 
    } 

    public function removeObject() 
    { 
     $this->objectList[0]->emptyWrapper(); 
     unset($this->objectList[0]); 
    } 
} 



class Wrapper { 

    private $object; 

    public function __construct($object) { 
     $this->object = $object; 
    } 

    public function __call($method, $args) { 
     return call_user_func_array(array($this->object, $method), $args); 
    } 

    public function __get($attr) { 
     return $this->object->$attr; 
    } 

    public function __set($attr, $value) { 
     $this->object->$attr = $value; 
    } 

    public function emptyWrapper() { 
     $this->object = null; 
    } 

} 

Vous pouvez utiliser cette idée d'emballage ou vous pouvez utiliser forcé indirection et poignées. Je préférerais plutôt utiliser l'indirection forcée; Dans le cas contraire, un appelant peut toujours conserver l'objet wrapper en vie, même s'il est relativement bon marché.

class myClass 
{ 
    public $objectList = array(); 

    public function __construct() 
    { 
     $objectList[] = new myObject(); 
    } 

    public function getObjectHandle() { 
     return 0; 
    } 

    public function removeObject($h) 
    { 
     unset($this->objectList[$h]); 
    } 

    public function call($h, $method, $args) { 
     call_user_func(array($this->objectList[$h], $method), $args); 
    } 

    public function get($h, $attr) { 
     return $this->objectList[$h]->$attr; 
    } 

    public function set($h, $attr, $value) { 
     $this->objectList[$h]->$attr = $value; 
    } 

} 

$myClass = new myClass(); 
$objectHandle = $myClass->getObjectHandle(); 
// example method call 
$myClass->call($objectHandle, 'some_method', array('arg1', 'arg2')); 
$myClass->removeObject($objectHandle); 
Questions connexes