Сброс переменной при ссылке в php - PullRequest
1 голос
/ 23 сентября 2010

У меня есть класс, который содержит массив объектов и имеет методы для возврата объекта из этого массива по ссылке. Существует также метод для удаления объекта из массива.

Однако, если у меня есть переменная, которая ссылается на объект из массива, и этот элемент не установлен, переменная по-прежнему имеет ссылку на него. Что мне нужно сделать в методе удаления, который уничтожит этот объект навсегда, включая ссылки на него.

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.

Так вот в чем проблема, с которой я столкнулся, мне нужно иметь возможность удалить из массива и удалить объект из памяти, чтобы переменные, ссылающиеся на этот объект, больше не могли использоваться.

Ответы [ 4 ]

0 голосов
/ 23 сентября 2010

Такова природа сборщика мусора в PHP. Чтобы убедиться, что вызывающий объект не поддерживает ссылку на ваш объект, вы должны убедиться, что он никогда не сможет коснуться исходного объекта. Вот идея:

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;
    }

}

Вы можете использовать эту идею обертки или принудительное косвенное обращение и дескрипторы. Я мог бы вместо этого использовать принудительное косвенное обращение; в противном случае вызывающая сторона может сохранить объект-оболочку живым, хотя это довольно дешево.

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);
0 голосов
/ 23 сентября 2010

Чтобы создать ссылку из возвращаемого значения, функция должна возвращаться по ссылке (вы уже сделали это), а присвоение - по ссылке.Поэтому вы должны написать:

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

Если вы сделаете это, ссылка действительно будет уничтожена.

Но если вы хотите уничтожить все переменные, имеющие этот объект в качестве значения (и которые не ссылок) тогда это невозможно.Вы можете удалить только реальные ссылки, но не переменные с одинаковым значением;)

0 голосов
/ 23 сентября 2010

Php работает с сборщиком мусора: если еще есть ссылка на объект, то объект не удаляется.

unset($this->objectList[0])

Не удаляет объект, но значение в $ this-> objectList,объект все еще существует, так как на него ссылается $ referencedObject.

Одно решение: когда вы удаляете объект, скажите ему, что он удаляется, и в этом объекте у вас есть логическое значение "isDeleted".Затем для каждого метода этого объекта проверьте, является ли isDeleted истиной, и в этом случае просто ничего не делайте.

0 голосов
/ 23 сентября 2010

Вы пробовали делать:

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

Является ли $ referencedObject все еще там после ввода этого &?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...