<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <HTML ><HEAD ><TITLE >构造函数中的引用</TITLE ><META NAME="GENERATOR" CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK REL="HOME" TITLE="PHP 手册" HREF="index.html"><LINK REL="UP" TITLE="类与对象(PHP 4)" HREF="language.oop.html"><LINK REL="PREVIOUS" TITLE="魔术函数 __sleep 和 __wakeup" HREF="language.oop.magic-functions.html"><LINK REL="NEXT" TITLE="对象的比较" HREF="language.oop.object-comparison.html"><META HTTP-EQUIV="Content-type" CONTENT="text/html; charset=UTF-8"></HEAD ><BODY CLASS="sect1" BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#840084" ALINK="#0000FF" ><DIV CLASS="NAVHEADER" ><TABLE SUMMARY="Header navigation table" WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" ><TR ><TH COLSPAN="3" ALIGN="center" >PHP 手册</TH ></TR ><TR ><TD WIDTH="10%" ALIGN="left" VALIGN="bottom" ><A HREF="language.oop.magic-functions.html" ACCESSKEY="P" >上一页</A ></TD ><TD WIDTH="80%" ALIGN="center" VALIGN="bottom" >章 18. 类与对象(PHP 4)</TD ><TD WIDTH="10%" ALIGN="right" VALIGN="bottom" ><A HREF="language.oop.object-comparison.html" ACCESSKEY="N" >下一页</A ></TD ></TR ></TABLE ><HR ALIGN="LEFT" WIDTH="100%"></DIV ><DIV CLASS="sect1" ><H1 CLASS="sect1" ><A NAME="language.oop.newref" >构造函数中的引用</A ></H1 ><P > 在构造函数中创建引用可能会导致混淆的结果。本节以教程形式帮助避免问题。 <DIV CLASS="informalexample" ><P ></P ><A NAME="AEN5634" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" CELLPADDING="5" ><TR ><TD ><code><font color="#000000"> <font color="#0000BB"><?php<br /></font><font color="#007700">class </font><font color="#0000BB">Foo </font><font color="#007700">{<br /> function </font><font color="#0000BB">Foo</font><font color="#007700">(</font><font color="#0000BB">$name</font><font color="#007700">) {<br /> </font><font color="#FF8000">// 在全局数组 $globalref 中建立一个引用<br /> </font><font color="#007700">global </font><font color="#0000BB">$globalref</font><font color="#007700">;<br /> </font><font color="#0000BB">$globalref</font><font color="#007700">[] = &</font><font color="#0000BB">$this</font><font color="#007700">;<br /> </font><font color="#FF8000">// 将名字设定为传递的值<br /> </font><font color="#0000BB">$this</font><font color="#007700">-></font><font color="#0000BB">setName</font><font color="#007700">(</font><font color="#0000BB">$name</font><font color="#007700">);<br /> </font><font color="#FF8000">// 并输出之<br /> </font><font color="#0000BB">$this</font><font color="#007700">-></font><font color="#0000BB">echoName</font><font color="#007700">();<br /> }<br /><br /> function </font><font color="#0000BB">echoName</font><font color="#007700">() {<br /> echo </font><font color="#DD0000">"<br />"</font><font color="#007700">,</font><font color="#0000BB">$this</font><font color="#007700">-></font><font color="#0000BB">name</font><font color="#007700">;<br /> }<br /><br /> function </font><font color="#0000BB">setName</font><font color="#007700">(</font><font color="#0000BB">$name</font><font color="#007700">) {<br /> </font><font color="#0000BB">$this</font><font color="#007700">-></font><font color="#0000BB">name </font><font color="#007700">= </font><font color="#0000BB">$name</font><font color="#007700">;<br /> }<br />}<br /></font><font color="#0000BB">?></font> </font> </code></TD ></TR ></TABLE ><P ></P ></DIV > </P ><P > 下面来检查一下用拷贝运算符 <TT CLASS="literal" >=</TT > 创建的 <CODE CLASS="varname" >$bar1</CODE > 和用引用运算符 <TT CLASS="literal" >=&</TT > 创建的 <CODE CLASS="varname" >$bar2</CODE > 有没有区别... <DIV CLASS="informalexample" ><P ></P ><A NAME="AEN5641" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" CELLPADDING="5" ><TR ><TD ><code><font color="#000000"> <font color="#0000BB"><?php<br />$bar1 </font><font color="#007700">= new </font><font color="#0000BB">Foo</font><font color="#007700">(</font><font color="#DD0000">'set in constructor'</font><font color="#007700">);<br /></font><font color="#0000BB">$bar1</font><font color="#007700">-></font><font color="#0000BB">echoName</font><font color="#007700">();<br /></font><font color="#0000BB">$globalref</font><font color="#007700">[</font><font color="#0000BB">0</font><font color="#007700">]-></font><font color="#0000BB">echoName</font><font color="#007700">();<br /><br /></font><font color="#FF8000">/* 输出:<br />set in constructor<br />set in constructor<br />set in constructor */<br /><br /></font><font color="#0000BB">$bar2 </font><font color="#007700">=& new </font><font color="#0000BB">Foo</font><font color="#007700">(</font><font color="#DD0000">'set in constructor'</font><font color="#007700">);<br /></font><font color="#0000BB">$bar2</font><font color="#007700">-></font><font color="#0000BB">echoName</font><font color="#007700">();<br /></font><font color="#0000BB">$globalref</font><font color="#007700">[</font><font color="#0000BB">1</font><font color="#007700">]-></font><font color="#0000BB">echoName</font><font color="#007700">();<br /><br /></font><font color="#FF8000">/* 输出:<br />set in constructor<br />set in constructor<br />set in constructor */<br /></font><font color="#0000BB">?></font> </font> </code></TD ></TR ></TABLE ><P ></P ></DIV > </P ><P > 显然没有区别,但实际上有一个非常重要的区别:<CODE CLASS="varname" >$bar1</CODE > 和 <CODE CLASS="varname" >$globalref[0]</CODE > 并没有被引用,它们不是同一个变量。这是因为“new”默认并不返回引用,而返回一个拷贝。 <DIV CLASS="note" ><BLOCKQUOTE CLASS="note" ><P ><B >注意: </B > 在返回拷贝而不是引用中并没有性能上的损失(因为 PHP 4 及以上版本使用了引用计数)。相反更多情况下工作于拷贝而不是引用上更好,因为建立引用需要一些时间而建立拷贝实际上不花时间(除非它们都不是大的数组或对象,而其中之一跟着另一个变,那使用引用来同时修改它们会更聪明一些)。 </P ></BLOCKQUOTE ></DIV > 要证明以上写的,看看下面的代码。 <DIV CLASS="informalexample" ><P ></P ><A NAME="AEN5648" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" CELLPADDING="5" ><TR ><TD ><code><font color="#000000"> <font color="#0000BB"><?php<br /></font><font color="#FF8000">// 现在改个名字,你预期什么结果?<br />// 你可能预期 $bar1 和 $globalref[0] 二者的名字都改了...<br /></font><font color="#0000BB">$bar1</font><font color="#007700">-></font><font color="#0000BB">setName</font><font color="#007700">(</font><font color="#DD0000">'set from outside'</font><font color="#007700">);<br /><br /></font><font color="#FF8000">// 但如同前面说的,并不是这样。<br /></font><font color="#0000BB">$bar1</font><font color="#007700">-></font><font color="#0000BB">echoName</font><font color="#007700">();<br /></font><font color="#0000BB">$globalref</font><font color="#007700">[</font><font color="#0000BB">0</font><font color="#007700">]-></font><font color="#0000BB">echoName</font><font color="#007700">();<br /><br /></font><font color="#FF8000">/* 输出为:<br />set from outside<br />set in constructor */<br /><br />// 现在看看 $bar2 和 $globalref[1] 有没有区别<br /></font><font color="#0000BB">$bar2</font><font color="#007700">-></font><font color="#0000BB">setName</font><font color="#007700">(</font><font color="#DD0000">'set from outside'</font><font color="#007700">);<br /><br /></font><font color="#FF8000">// 幸运的是它们不但相同,根本就是同一个变量。<br />// 因此 $bar2->name 和 $globalref[1]->name 也是同一个变量。<br /></font><font color="#0000BB">$bar2</font><font color="#007700">-></font><font color="#0000BB">echoName</font><font color="#007700">();<br /></font><font color="#0000BB">$globalref</font><font color="#007700">[</font><font color="#0000BB">1</font><font color="#007700">]-></font><font color="#0000BB">echoName</font><font color="#007700">();<br /><br /></font><font color="#FF8000">/* 输出为:<br />set from outside<br />set from outside */<br /></font><font color="#0000BB">?></font> </font> </code></TD ></TR ></TABLE ><P ></P ></DIV > </P ><P > 最后给出另一个例子,试着理解它。 <DIV CLASS="informalexample" ><P ></P ><A NAME="AEN5651" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" CELLPADDING="5" ><TR ><TD ><code><font color="#000000"> <font color="#0000BB"><?php<br /></font><font color="#007700">class </font><font color="#0000BB">A </font><font color="#007700">{<br /> function </font><font color="#0000BB">A</font><font color="#007700">(</font><font color="#0000BB">$i</font><font color="#007700">) {<br /> </font><font color="#0000BB">$this</font><font color="#007700">-></font><font color="#0000BB">value </font><font color="#007700">= </font><font color="#0000BB">$i</font><font color="#007700">;<br /> </font><font color="#FF8000">// 试着想明白为什么这里不需要引用<br /> </font><font color="#0000BB">$this</font><font color="#007700">-></font><font color="#0000BB">b </font><font color="#007700">= new </font><font color="#0000BB">B</font><font color="#007700">(</font><font color="#0000BB">$this</font><font color="#007700">);<br /> }<br /><br /> function </font><font color="#0000BB">createRef</font><font color="#007700">() {<br /> </font><font color="#0000BB">$this</font><font color="#007700">-></font><font color="#0000BB">c </font><font color="#007700">= new </font><font color="#0000BB">B</font><font color="#007700">(</font><font color="#0000BB">$this</font><font color="#007700">);<br /> }<br /><br /> function </font><font color="#0000BB">echoValue</font><font color="#007700">() {<br /> echo </font><font color="#DD0000">"<br />"</font><font color="#007700">,</font><font color="#DD0000">"class "</font><font color="#007700">,</font><font color="#0000BB">get_class</font><font color="#007700">(</font><font color="#0000BB">$this</font><font color="#007700">),</font><font color="#DD0000">': '</font><font color="#007700">,</font><font color="#0000BB">$this</font><font color="#007700">-></font><font color="#0000BB">value</font><font color="#007700">;<br /> }<br />}<br /><br /><br />class </font><font color="#0000BB">B </font><font color="#007700">{<br /> function </font><font color="#0000BB">B</font><font color="#007700">(&</font><font color="#0000BB">$a</font><font color="#007700">) {<br /> </font><font color="#0000BB">$this</font><font color="#007700">-></font><font color="#0000BB">a </font><font color="#007700">= &</font><font color="#0000BB">$a</font><font color="#007700">;<br /> }<br /><br /> function </font><font color="#0000BB">echoValue</font><font color="#007700">() {<br /> echo </font><font color="#DD0000">"<br />"</font><font color="#007700">,</font><font color="#DD0000">"class "</font><font color="#007700">,</font><font color="#0000BB">get_class</font><font color="#007700">(</font><font color="#0000BB">$this</font><font color="#007700">),</font><font color="#DD0000">': '</font><font color="#007700">,</font><font color="#0000BB">$this</font><font color="#007700">-></font><font color="#0000BB">a</font><font color="#007700">-></font><font color="#0000BB">value</font><font color="#007700">;<br /> }<br />}<br /><br /></font><font color="#FF8000">// 试着理解为什么这里一个简单的拷贝会在下面用 *<br />// 标出来的行中产生预期之外的结果<br /></font><font color="#0000BB">$a </font><font color="#007700">=& new </font><font color="#0000BB">A</font><font color="#007700">(</font><font color="#0000BB">10</font><font color="#007700">);<br /></font><font color="#0000BB">$a</font><font color="#007700">-></font><font color="#0000BB">createRef</font><font color="#007700">();<br /><br /></font><font color="#0000BB">$a</font><font color="#007700">-></font><font color="#0000BB">echoValue</font><font color="#007700">();<br /></font><font color="#0000BB">$a</font><font color="#007700">-></font><font color="#0000BB">b</font><font color="#007700">-></font><font color="#0000BB">echoValue</font><font color="#007700">();<br /></font><font color="#0000BB">$a</font><font color="#007700">-></font><font color="#0000BB">c</font><font color="#007700">-></font><font color="#0000BB">echoValue</font><font color="#007700">();<br /><br /></font><font color="#0000BB">$a</font><font color="#007700">-></font><font color="#0000BB">value </font><font color="#007700">= </font><font color="#0000BB">11</font><font color="#007700">;<br /><br /></font><font color="#0000BB">$a</font><font color="#007700">-></font><font color="#0000BB">echoValue</font><font color="#007700">();<br /></font><font color="#0000BB">$a</font><font color="#007700">-></font><font color="#0000BB">b</font><font color="#007700">-></font><font color="#0000BB">echoValue</font><font color="#007700">(); </font><font color="#FF8000">// *<br /></font><font color="#0000BB">$a</font><font color="#007700">-></font><font color="#0000BB">c</font><font color="#007700">-></font><font color="#0000BB">echoValue</font><font color="#007700">();<br /></font><font color="#0000BB">?></font> </font> </code></TD ></TR ></TABLE ><P >上例将输出:</P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" CELLPADDING="5" ><TR ><TD ><PRE CLASS="screen" >class A: 10 class B: 10 class B: 10 class A: 11 class B: 11 class B: 11</PRE ></TD ></TR ></TABLE ><P ></P ></DIV > </P ></DIV ><DIV CLASS="NAVFOOTER" ><HR ALIGN="LEFT" WIDTH="100%"><TABLE SUMMARY="Footer navigation table" WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" ><TR ><TD WIDTH="33%" ALIGN="left" VALIGN="top" ><A HREF="language.oop.magic-functions.html" ACCESSKEY="P" >上一页</A ></TD ><TD WIDTH="34%" ALIGN="center" VALIGN="top" ><A HREF="index.html" ACCESSKEY="H" >起始页</A ></TD ><TD WIDTH="33%" ALIGN="right" VALIGN="top" ><A HREF="language.oop.object-comparison.html" ACCESSKEY="N" >下一页</A ></TD ></TR ><TR ><TD WIDTH="33%" ALIGN="left" VALIGN="top" >魔术函数 <TT CLASS="literal" >__sleep</TT > 和 <TT CLASS="literal" >__wakeup</TT ></TD ><TD WIDTH="34%" ALIGN="center" VALIGN="top" ><A HREF="language.oop.html" ACCESSKEY="U" >上一级</A ></TD ><TD WIDTH="33%" ALIGN="right" VALIGN="top" >对象的比较</TD ></TR ></TABLE ></DIV ></BODY ></HTML >