Механизм работы reference

Whatsername

Новичок
Механизм работы reference

Читаю статью Александра Грималовского (Flying) о references.
Уже две недели бьюсь над тем, что пытаюсь написать пример следующему (выделил красным):


$obj = &new Object();
$obj = new Object();

На первый взгляд разница между двумя этими путями невелика - все равно в результате мы получаем экземпляр необходимого нам объекта. Однако разница есть и она таится в конструкторе объекта. Все дело в том, что конструктор объекта вызывается до того, как завершится работа оператора new. Поэтому, если в конструкторе объекта вы создали какие-либо references в переменных объекта, используя для этого переменную $this, то все эти references будут потеряны! Так что вам необходимо четко следить за тем, как именно вы создаете экземпляры ваших объектов, чтобы избежать подобных, далеко не очевидных, проблем.


Не прошу написать этот пример за меня. Но, если не трудно, объясните мне по-руззки: о чем Flying ведет речь.
У меня references не бьются, хоть тресни.

Статья: http://providers.ru/articles/php/references.html

Спасибо.
 

Breeze

goshogun
Команда форума
Партнер клуба
вот и у меня не бьются.. может это и справедливо для какого-нить 4.0.6, но с более поздними я этого не наблюдал, хотя объектами пользуюсь достаточно часто.

$obj = &new Object(); -- в пятой версии это вообще deprecated, если не ошибаюсь.

-~{}~ 02.03.05 17:39:

а вообще статьи выглядят очень древними.. например про сессии.. о $_SESSION ни одного упоминания.
 

Whatsername

Новичок
Спасибо, Breeze, статьи действительно трехлетней давности, $_SESSION тогда и вовсе не было. Но про reference написаны до того толково, что хочется разобраться в них до последней строчки.

tony, ты о чем?
 

IntenT

SkyDiver
PHP:
<?
class B {
    
    function B(&$parent){
        $this->parent = &$parent;
        $this->parent->var = 10;
    }

    function doit(){
        $this->parent->var = 20;    
    }

}

class A {
    
    function A(){
        $this->child = new B($this);
    }

    function doit(){
        $this->child->doit();
        echo $this->var."<br>";
    }
}

$a = new A();
$a->doit();

$b =& new A();
$b->doit(); 
?>
Речь естественно о 4-ке
 

Whatsername

Новичок
IntenT,
огромное тебе спасибо за этот пример. Не хотел ничего постить до того как разрулю его полность, но это может продлиться дольше, чем я планировал =))

Не до конца понятно зачем ты используешь "parent" в качестве переменной, когда это ключевое слово... но это не суть.

Не могу уловить где же именно происходит потеря ссылки.

Anyway, большое тебе спасибо за помощь.
 

slego

Новичок
Да, пример, хороший, но, к сожалению, он опять абстрактный, т.е. в очередной раз демонстрирует всего-лишь "хитрый" МЕХАНИЗМ работы ссылок. В мануалах и хелпах такого оооочень много.
Может быть кто-нибудь может привести пример, в котором для достижения конкретной задачи, без "=&" обойтись просто невозможно? :rolleyes: :confused:
 

IntenT

SkyDiver
slego
приведен вполне конкретный код, который решает вполне конкретную задачу - в чайлде создает ссылку на парент.

без =& нельзя обойтись там, где необходимо создание ссылок.
 

slego

Новичок
Автор оригинала: IntenT
приведен вполне конкретный код, который решает вполне конкретную задачу - в чайлде создает ссылку на парент.
Код - не конкретный, код - абстрактный. Где такое может понадобится - не понятно.
Неудачно выразился. Под конкретным я имел в виду - код, так сказать, из жизни, какой-нибудь реальный пример. Хотя, это, наверное, проблематично будет.

без =& нельзя обойтись там, где необходимо создание ссылок.
класс! :)
А без "=" нельзя обойтись там, где ты хочешь значению одной переменной приравнять значение другой. :)
 

IntenT

SkyDiver
Вот вполне конкретный код, незнаю правда чем он тебе поможет. Код добавляет контрол к экземпляру контрола, создает ссылки на контрол верхего уровня и на родительский контрол.
PHP:
    /**
    * Method Adds the specified Control object to the controls collection.
    * @param       (object structure)    $name   Object instance
    * @access public
    */
    function AddControl(&$object) {
        if (!is_object($object))  {
            return;
        }
        $object->Parent = &$this;
        $object->Page = &$this->Page;
        $this->Controls[$object->Name] = &$object;
        if ($this->_state >= WEB_CONTROL_INITIALIZED) {
            $object->initRecursive();
            if ($this->_state >= WEB_CONTROL_LOADED)
            $object->loadRecursive();
        }
    }
Тот код, который я привел выше показывает всего-лишь особенности поведения ссылки на экземпляр этого-же класса, созданной в конструкторе.
Здесь 2 ключевых момента - ссылка на $this, и то, что она создается в конструкторе.
Если создание ссылки вынести из конструктора, или это будет ссылка не на $this - то будет абсолютно одинаково работать при
PHP:
$a = new A(); 
$a->doit();
и
PHP:
$b =& new A(); 
$b->doit();
 

slego

Новичок
во-во-во, начинает доходить :) Спасибо, что не лень отвечать :)
 

Whatsername

Новичок
IntenT, большое спасибо.
Можно тебя еще спросить о твоем примере?
Если создать только один объект, и присовить его переменной по значению:

$a = new A();

тот_самый_ объект, создаваемый изначально, а затем копируемый, останется жив или нет? Подозреваю, что останется, так как

child -> parent

будет указывать на него, и объект не будет удален. Как бы это проверить?
 

IntenT

SkyDiver
Violator
Объект "жив" не будет, вернее если он не будет referenced, этот объект удалится из памяти. Но его можно связать с переменной, тогда он останется жить.
Вот пример, который показывает это
PHP:
<? 
class A { 
    var $foo = "moo"; 
    function A(){ 
        global $A;
        $A = $this;
    } 

} 

$a = new A(); 
$a->foo = "bar";
print_r($a);
print_r($A);

?>
 

Whatsername

Новичок
IntenT,
вероятно, я не очень точно сформулировал мысль. Поясню на примере:
PHP:
<? 
class B { 
     
    function B(&$parent){ 
        $this->parent = &$parent; 
        $this->parent->var = 10; 
    } 

    function doit(){ 
        $this->parent->var = 20;     
    } 

} 

class A { 
     
    function A(){ 
        $this->child = new B($this); 
    } 

    function doit(){ 
        $this->child->doit(); 
        echo $this->var."<br>"; 
    } 
}

$a = new A();
?>
Создается объект класса А и _копируется_ в переменную а. Теперь на изначально созданный объект указывает:
$a -> child -> parent // ссылка осталась - объект живет.

Если сделать:
var_dump($a -> child -> parent) - увидим все его свойства.

А если вызвать метод _скопированного_ объекта, этот метод будет действовать над изначальным объектом, это можно проверить таким же образом.

Как считаешь - все точно?
 

vitus

мимо проходил
что за лабудень ?

PHP:
/*так работает*/
$b=&$a;

$c=&$b;

$a = "hallo world"; 

echo "$c-$b<br>";//$c is not empty 
/***************************************/


/*а так - не работает*/
$c=&$b;

$b=&$a;

$a = "hallo world"; 

echo "$c-$b<br>";//$c is empty  ??? 
/***************************************/
какая неприятность :)
 

vitus

мимо проходил
неа, не баг - фича :D
1. - $b ссылается на область $a, $c ссылается на область $a, $a получает значение

2. - $c ссылается на область $b, $b ссылается на область $a при этом перестаёт ссылаться на свою собственную область, $a получает значение, а $c не получает.


-~{}~ 14.03.05 13:18:

это следствие схемы, описанной в статье
 

slego

Новичок
Странно, просто скопировал и запустил вышеприведенный код и у меня вывелось
PHP:
hallo world-hallo world
hallo world-hallo world
:confused:

PHP Version 4.3.9
Apache 1.3.31
Windows 2000 SP1
 
Сверху