Создание объекта по ссылке.

XtremallyPurpur

Новичок
Создание объекта по ссылке.

Добрый день.
В рекомендации к PEAR написано, что объекты из классов PEAR желательно создавать по ссылке :
PHP:
  $obj = &new PEAR_class();
а почему?
И если создается объект так:
PHP:
  $obj = new PEAR_class();
то говорится о копии. Какая копия имеется ввиду?

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

гоша

Guest
В php4 объекты присваиваются по значению (как и всё остальное).

$a=$b;

мы получаем два разных объекта.
 

XtremallyPurpur

Новичок
гоша
это понятно,
я имел ввиду при создании объекта.
В документации по PEAR говорится о создании некой копии. Копии чего, если объекта еще нет?
 

Yurik

/dev/null
new PEAR_class(); - создать класс
$obj = new PEAR_class(); - создать класс и скопировать его в $obj
$obj = &new PEAR_class(); - создать класс и поместить в $obj ссылку на него
 

XtremallyPurpur

Новичок
Yurik
Понятно, это механизм работы.
Тогда, вот такая заморочка это что:
PHP:
 class a{
   var $variable;
   function a($b){
     $this->variable = $b;
   }
 }

 $myclass = [b]&[/b]new a(12);

 $myclass2 = $myclass;

 $myclass2->variable = 10;

 print $myclass->variable;
Печатает 12. То есть $myclass2 не является ссылкой на объект $myclass! Копируется не ссылка, а сам объект.
 

Demiurg

Guest
$myclass2 = &$myclass;
в
$myclass2 = $myclass;
происходит копирование, тк $myclass2 в этом случае не является ссылкой.
 

XtremallyPurpur

Новичок
Demiurg
Понятно, если хочется ссылку - всегда приходится указывать, что копируется ссылка, а не сам объект. Иначе PHP интерпретирует, что мы хотим получить копию объекта. Я правильно понял?
Пардон за сумбурность.
Yurik
$obj = new PEAR_class(); - создать класс и скопировать его в $obj.
А зачем сначала создавать объект, а затем присваивать его копию переменной, а не сразу присваивать переменной объект?

-~{}~ 10.02.04 15:33:

2All
Ага, начало доходить. В PHP "=" всегда копирует, значит при создании объекта
вот так
PHP:
$obj = new class();
скопируется результат выполнения new, то есть фактически получается два объекта. Так?
 

Demiurg

Guest
XtremallyPurpur
да, правильно, если ты не указываешь, что хочешь ссылку, то php копирует объект.

>то есть фактически получается два объекта.
вряд ли...
 

XtremallyPurpur

Новичок
Demiurg
Так в чем же смысл фразы:
the object registered in PEAR's shutdown list will be a copy of the object at the time the constructor is called
т.е. что-то в этом роде:
В списке объектов PEAR будет копия.
Вразумите пожалуйста, что имеется ввиду, копия чего, если второй объект не создается?
 

kvn

programmer
Фишка вся в том, что в PHP нет деструкторов объекта, как это подразумевает теория ООП.
Поэтому ребята из PEAR реализовали эмуляцию деструкторов (http://pear.php.net/manual/ru/core.pear.pear.intro.php#destructors)

Если рассмотреть более детально, то это реализовано через register_shutdown_function(), соотв. метод ::_ClassName() будет вызываться после завершения работы скрипта.
Но эта шатдаун-функция должна вызвать метод именно того объекта, с которым ты работаешь, поэтому присутствует требование о создании объекта по ссылке, в противном случае вызовется деструктор копии объекта.

более детально смотри исходник PEAR.php.
 

XtremallyPurpur

Новичок
kvn
Спасибо.
Но я спрашивал несколько другое -
написано "создается копия при следующем создании объекта:
PHP:
$obj = new class();
".
Так вот, куда девается оригинал? Что это за оригинал. Вот Demiurg сказал, что два объекта не создается, а копия чего тогда имеется ввиду? Я чего-то въехать не могу, похоже все таки так:
операция присвания имеет семантику копирования, следовательно, копирует результат выполнения new. Итого - два объекта. Только что тогда с оригиналом, он сразу уничтожается или по завершении выполнения скрипта?
 

.des.

Поставил пиво кому надо ;-)
XtremallyPurpur неужели Вам сложно заглянуть в мануал?

PHP:
class A {
	var $v;
	function A($v)
	{
		$this->v = $v;
		register_shutdown_function(array(&$this, '_shutdown'));
	
	}
	function _shutdown()
	{
		echo "shutdown $this->v\n";
	}
}

$a = new A(10);
$a->v = 11;
echo $a->v;
как видите shutdown function вызывается для совсем другого объекта. Не совсем то, что ожидалось, правда?
Замените $a = new A(10); на $a =& new A(10);
и сравните вывод.

и если внимательно прочесть мануал, то все становится понятно из приведенных там примеров.
http://lv.php.net/manual/ru/language.oop.newref.php
PHP:
class A {
	var $b;
	var $v;
	function A($v)
	{
		$this->v = $v;
		$this->b =& new B($this);
	}
}

class B {
	var $a;
	function B(&$a) {
		$this->a =& $a;
	}
}

$a = new A(1); 
echo $a->v."\n"; 
echo $a->b->a->v."\n"; 
$a->v = 2; 
echo $a->v."\n"; 
echo $a->b->a->v."\n";
 

XtremallyPurpur

Новичок
.des.
ОК. Попытаюсь спросить по-другому.

is a difference between $ob1 which has been created using the copy = operator and $ob2 which has been created using the reference =& operator

Это прозрачно для меня. Я пытаюсь спросить про ОРИГИНАЛ объекта, созданного new.

При $ob=new class() порядок создания объекта такой:
1. new создает объект, назовем его I;
2. "=" копирует объект I, получается объект II.
Так?
 

.des.

Поставил пиво кому надо ;-)
Вы первый мой пример запускали?
Еще вопросы?
 

XtremallyPurpur

Новичок
.des.
да, запускал. Спасибо.

Итак, мои выводы:

1. PHP при использовании оператора "=" ВСЕГДА создает копию.

Причем, даже если выражение в правой части является ссылкой на объект, выражение в левой будет копией самого объекта, на который ссылается выражение в правой части, а не копией ссылки, на примере
PHP:
$ob1 = &new class();
$ob2 = $ob1; // $ob2 - копия объекта $ob1, а не ссылка
2. При создании объекта из класса нужно быть осторожным, и четко представлять себе хотим мы работать с самим объектом (&new) или его копией (new). Причем, при создании копии получается, что производительность повышается (трактовка мануала).

Все правильно?
 

PhpGuest

Guest
Еще помница какаято трабла была с переменой $this в конструкторе обьекта - действия вида
$a=$this
$a=&$this

всегда создовали копию обьекта

использование $this вне конструктора - работает нормально
 

trigger

Guest
XtremallyPurpur
Мне кажется, я понимаю, в чем у тебя непонятки.

В PHP нет "ссылок" есть только "передача по ссылке". Для себя я считаю, что все переменные -- ссылки, только если мы пытаемся использовать их, неважно как, PHP сначала переходит по этим ссылкам к нужной области в памяти и только потом что-то делает. В дальнейшем я буду оперировать общими понятиями, а не моими.

$ob1 -- это не ссылка, а сам объект. Только после "&new class()" вожжи от созданного объекта отдаются $ob1. Если бы "&" не было, то создавался бы второй объект, вторые вожжи отдавались бы в $ob1, а первые вожжи терялись.
PHP:
$ob2 = $ob1; // $ob2 - копия объекта $ob1, а не ссылка
Да, так как $ob1 -- это объект, а не ссылка. После "&new" ему объект передался по ссылке, а не передалась ссылка на объект. Если бы мы написали "$ob2 = &$ob1", то $ob2 давались бы еще одни вожжи от объекта, а не ссылка на объект.
Так вот, куда девается оригинал? Что это за оригинал.
А всё! Не знаю, что там PHP c ним делает, только оригинала мы больше не увидим, так как больше ни у одной переменной нету вожжей от объекта. Он больше для нас недоступен.

Самое главное, что надо запомнить: в PHP нету ссылок. Нету такого типа переменных -- ссылка. Все переменные полноценны. Есть только передача по ссылке.
 

Demiurg

Guest
trigger
что тогда ты называешь ссылками ?

при передаче в функцию в php используется "copy on write", по карайне мере для строк. То есть функция получает ссылку, даже если мы этого явно не указываем, при попытке изменить строку сначала делается копия.
 

PhpGuest

Guest
Автор оригинала: trigger
Самое главное, что надо запомнить: в PHP нету ссылок. Нету такого типа переменных -- ссылка. Все переменные полноценны. Есть только передача по ссылке.
где то видел замечателдьную схему реализации переменных в php:

там две таблицы (списка) - одна (1) массив имен переменных - другая (2)массив данных.
Каждый элемент из (1) содержит указатель на сответсвующий в (2)

Операция = - создает новый элемент в (1) и дублирует ссответсвующий в (2) делая на него ссылку из (1)

Операция =& - создает новый жлемент в (1) и делает ссылку из него на значение переменной спарва от =& (не дублируя ел. в (2) )

передача в функцию ($a) делает имя для локальной (1) и копию в локальной (2)

передача в функцию (&$a) делает имя для локальной (1) и ссылку из нее на эл глобадльной таблицы (2)

инструкция global - тоже создает элемнт для локальной (1) делая из него ссылку на данные в глобальной (2)
 
Сверху