构造函数中的引用

在构造函数中创建引用可能会导致混淆的结果。本节以教程形式帮助避免问题。

<?php
class Foo {
   function
Foo($name) {
       
// &#22312;&#20840;&#23616;&#25968;&#32452; $globalref &#20013;&#24314;&#31435;&#19968;&#20010;&#24341;&#29992;
       
global $globalref;
       
$globalref[] = &$this;
       
// &#23558;&#21517;&#23383;&#35774;&#23450;&#20026;&#20256;&#36882;&#30340;&#20540;
       
$this->setName($name);
       
// &#24182;&#36755;&#20986;&#20043;
       
$this->echoName();
   }

   function
echoName() {
       echo
"<br />",$this->name;
   }

   function
setName($name) {
       
$this->name = $name;
   }
}
?>

下面来检查一下用拷贝运算符 = 创建的 $bar1 和用引用运算符 =& 创建的 $bar2 有没有区别...

<?php
$bar1
= new Foo('set in constructor');
$bar1->echoName();
$globalref[0]->echoName();

/* &#36755;&#20986;&#65306;
set in constructor
set in constructor
set in constructor */

$bar2 =& new Foo('set in constructor');
$bar2->echoName();
$globalref[1]->echoName();

/* &#36755;&#20986;&#65306;
set in constructor
set in constructor
set in constructor */
?>

显然没有区别,但实际上有一个非常重要的区别:$bar1$globalref[0] 并没有被引用,它们不是同一个变量。这是因为“new”默认并不返回引用,而返回一个拷贝。

注意:

在返回拷贝而不是引用中并没有性能上的损失(因为 PHP 4 及以上版本使用了引用计数)。相反更多情况下工作于拷贝而不是引用上更好,因为建立引用需要一些时间而建立拷贝实际上不花时间(除非它们都不是大的数组或对象,而其中之一跟着另一个变,那使用引用来同时修改它们会更聪明一些)。

要证明以上写的,看看下面的代码。

<?php
// &#29616;&#22312;&#25913;&#20010;&#21517;&#23383;&#65292;&#20320;&#39044;&#26399;&#20160;&#20040;&#32467;&#26524;&#65311;
// &#20320;&#21487;&#33021;&#39044;&#26399; $bar1 &#21644; $globalref[0] &#20108;&#32773;&#30340;&#21517;&#23383;&#37117;&#25913;&#20102;...
$bar1->setName('set from outside');

// &#20294;&#22914;&#21516;&#21069;&#38754;&#35828;&#30340;&#65292;&#24182;&#19981;&#26159;&#36825;&#26679;&#12290;
$bar1->echoName();
$globalref[0]->echoName();

/* &#36755;&#20986;&#20026;&#65306;
set from outside
set in constructor */

// &#29616;&#22312;&#30475;&#30475; $bar2 &#21644; $globalref[1] &#26377;&#27809;&#26377;&#21306;&#21035;
$bar2->setName('set from outside');

// &#24184;&#36816;&#30340;&#26159;&#23427;&#20204;&#19981;&#20294;&#30456;&#21516;&#65292;&#26681;&#26412;&#23601;&#26159;&#21516;&#19968;&#20010;&#21464;&#37327;&#12290;
// &#22240;&#27492; $bar2->name &#21644; $globalref[1]->name &#20063;&#26159;&#21516;&#19968;&#20010;&#21464;&#37327;&#12290;
$bar2->echoName();
$globalref[1]->echoName();

/* &#36755;&#20986;&#20026;&#65306;
set from outside
set from outside */
?>

最后给出另一个例子,试着理解它。

<?php
class A {
   function
A($i) {
       
$this->value = $i;
       
// &#35797;&#30528;&#24819;&#26126;&#30333;&#20026;&#20160;&#20040;&#36825;&#37324;&#19981;&#38656;&#35201;&#24341;&#29992;
       
$this->b = new B($this);
   }

   function
createRef() {
       
$this->c = new B($this);
   }

   function
echoValue() {
       echo
"<br />","class ",get_class($this),': ',$this->value;
   }
}


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

   function
echoValue() {
       echo
"<br />","class ",get_class($this),': ',$this->a->value;
   }
}

// &#35797;&#30528;&#29702;&#35299;&#20026;&#20160;&#20040;&#36825;&#37324;&#19968;&#20010;&#31616;&#21333;&#30340;&#25335;&#36125;&#20250;&#22312;&#19979;&#38754;&#29992; *
// &#26631;&#20986;&#26469;&#30340;&#34892;&#20013;&#20135;&#29983;&#39044;&#26399;&#20043;&#22806;&#30340;&#32467;&#26524;
$a =& new A(10);
$a->createRef();

$a->echoValue();
$a->b->echoValue();
$a->c->echoValue();

$a->value = 11;

$a->echoValue();
$a->b->echoValue(); // *
$a->c->echoValue();
?>

上例将输出:

class A: 10
class B: 10
class B: 10
class A: 11
class B: 11
class B: 11