构造函数中的引用

构造函数中的引用

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

 

<?php
class Foo
{
   function
Foo($name)
   {
      
// 在全局数组 $globalref 中建立一个引用
      
global $globalref;
      
$globalref[] = &$this;
      
// 将名字设定为传递的值
      
$this->setName($name);
      
// 并输出之
      
$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();

/* 输出:
set in constructor
set in constructor
set in constructor */

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

/* 输出:
set in constructor
set in constructor
set in constructor */
?>

 

 

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

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

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

 

<?php
// 现在改个名字,你预期什么结果?
// 你可能预期 $bar1 和 $globalref[0] 二者的名字都改了...
$bar1->setName('set from outside');

// 但如同前面说的,并不是这样。
$bar1->echoName();
$globalref[0]->echoName();

/* 输出为:
set from outside
set in constructor */

// 现在看看 $bar2 和 $globalref[1] 有没有区别
$bar2->setName('set from outside');

// 幸运的是它们不但相同,根本就是同一个变量。
// 因此 $bar2->name 和 $globalref[1]->name 也是同一个变量。
$bar2->echoName();
$globalref[1]->echoName();

/* 输出为:
set from outside
set from outside */
?>

 

 

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

 

<?php
class A
{
   function
A($i)
   {
      
$this->value = $i;
      
// 试着想明白为什么这里不需要引用
      
$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;
   }
}

// 试着理解为什么这里一个简单的拷贝会在下面用 *
// 标出来的行中产生预期之外的结果
$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
*/
?>

 

 



<script type="text/javascript"> </script> <script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"> </script> name="google_ads_frame" marginwidth="0" marginheight="0" src="http://pagead2.googlesyndication.com/pagead/ads?client=ca-pub-1374401628164525&dt=1140873654750&lmt=1037959972&alternate_ad_url=http%3A%2F%2Fwww.phpe.net%2Fgoogle_adsense_script.html&prev_fmts=160x600_as&format=468x60_as&output=html&channel=5447751394&pv_ch=5447751394%2B&url=http%3A%2F%2Fwww.phpe.net%2Fmanual%2Flanguage.oop.newref.php&color_bg=FFFFFF&color_text=333333&color_link=000099&color_url=666666&color_border=FFFFFF&ad_type=text&cc=699&u_h=768&u_w=1024&u_ah=738&u_aw=1024&u_cd=32&u_tz=480&u_his=2&u_java=true" frameborder="0" width="0" scrolling="no" height="0" allowtransparency="allowtransparency">

add a note  User Contributed Notes
构造函数中的引用
rpav at NOSPAMusers dot sf dot net
14-Aug-2002 06:13
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Ah HA! I just found an easy workaround with a bit of playing.  This works:

--- cut ---
$OBJECTS = array();

class Object {
  function &Object() {
       global $OBJECTS;
      $OBJECTS[] = &$this;
   }

   function _init() {

  }
}

class Derived {
   function &Derived() {
      Object::Object();
   }
}

function blah() {
   global $FOO;

   $x =& new Derived;
   $GLOBALS['FOO'] = &$x;
   $x->foo = 42;
   display("x", $x);
}

function display($text, &$o) {
  echo("($text) =>" . serialize($o));
}

blah();
display("GLOBALS[FOO]", $GLOBALS['FOO']);
display("OBJECTS", $OBJECTS);
--- cut ---

As you can see, simply adding & before the constructor to make it return a reference does the trick.  The bit about "returning a copy by default" lead me to try this trick, and it seems to work. Have fun!

-rjp
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值