<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <HTML ><HEAD ><TITLE >类与对象(PHP 4)</TITLE ><META NAME="GENERATOR" CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK REL="HOME" TITLE="PHP 手册" HREF="index.html"><LINK REL="UP" TITLE="语言参考" HREF="langref.html"><LINK REL="PREVIOUS" TITLE="内部(内置)函数" HREF="functions.internal.html"><LINK REL="NEXT" TITLE="继承" HREF="keyword.extends.html"><META HTTP-EQUIV="Content-type" CONTENT="text/html; charset=UTF-8"></HEAD ><BODY CLASS="chapter" 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="functions.internal.html" ACCESSKEY="P" >上一页</A ></TD ><TD WIDTH="80%" ALIGN="center" VALIGN="bottom" ></TD ><TD WIDTH="10%" ALIGN="right" VALIGN="bottom" ><A HREF="keyword.extends.html" ACCESSKEY="N" >下一页</A ></TD ></TR ></TABLE ><HR ALIGN="LEFT" WIDTH="100%"></DIV ><DIV CLASS="chapter" ><H1 ><A NAME="language.oop" >章 18. 类与对象(PHP 4)</A ></H1 ><DIV CLASS="TOC" ><DL ><DT ><B >目录</B ></DT ><DT ><A HREF="language.oop.html#keyword.class" ><TT CLASS="literal" >类</TT ></A ></DT ><DT ><A HREF="keyword.extends.html" ><TT CLASS="literal" >继承</TT ></A ></DT ><DT ><A HREF="language.oop.constructor.html" >构造函数</A ></DT ><DT ><A HREF="keyword.paamayim-nekudotayim.html" >范围解析操作符(<TT CLASS="literal" >::</TT >)</A ></DT ><DT ><A HREF="keyword.parent.html" ><TT CLASS="literal" >parent</TT ></A ></DT ><DT ><A HREF="language.oop.serialization.html" >序列化对象 - 会话中的对象</A ></DT ><DT ><A HREF="language.oop.magic-functions.html" >魔术函数 <TT CLASS="literal" >__sleep</TT > 和 <TT CLASS="literal" >__wakeup</TT ></A ></DT ><DT ><A HREF="language.oop.newref.html" >构造函数中的引用</A ></DT ><DT ><A HREF="language.oop.object-comparison.html" >对象的比较</A ></DT ></DL ></DIV ><DIV CLASS="sect1" ><H1 CLASS="sect1" ><A NAME="keyword.class" ><TT CLASS="literal" >类</TT ></A ></H1 ><P > 类是变量与作用于这些变量的函数的集合。使用下面的语法定义一个类: <DIV CLASS="informalexample" ><P ></P ><A NAME="AEN5454" ></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">Cart </font><font color="#007700">{<br /> var </font><font color="#0000BB">$items</font><font color="#007700">; </font><font color="#FF8000">// 购物车中的物品<br /><br /> // 将 $num 个 $artnr 物品加入购物车<br /><br /> </font><font color="#007700">function </font><font color="#0000BB">add_item</font><font color="#007700">(</font><font color="#0000BB">$artnr</font><font color="#007700">, </font><font color="#0000BB">$num</font><font color="#007700">) {<br /> </font><font color="#0000BB">$this</font><font color="#007700">-></font><font color="#0000BB">items</font><font color="#007700">[</font><font color="#0000BB">$artnr</font><font color="#007700">] += </font><font color="#0000BB">$num</font><font color="#007700">;<br /> }<br /><br /> </font><font color="#FF8000">// 将 $num 个 $artnr 物品从购物车中取出<br /><br /> </font><font color="#007700">function </font><font color="#0000BB">remove_item</font><font color="#007700">(</font><font color="#0000BB">$artnr</font><font color="#007700">, </font><font color="#0000BB">$num</font><font color="#007700">) {<br /> if (</font><font color="#0000BB">$this</font><font color="#007700">-></font><font color="#0000BB">items</font><font color="#007700">[</font><font color="#0000BB">$artnr</font><font color="#007700">] > </font><font color="#0000BB">$num</font><font color="#007700">) {<br /> </font><font color="#0000BB">$this</font><font color="#007700">-></font><font color="#0000BB">items</font><font color="#007700">[</font><font color="#0000BB">$artnr</font><font color="#007700">] -= </font><font color="#0000BB">$num</font><font color="#007700">;<br /> return </font><font color="#0000BB">true</font><font color="#007700">;<br /> } elseif (</font><font color="#0000BB">$this</font><font color="#007700">-></font><font color="#0000BB">items</font><font color="#007700">[</font><font color="#0000BB">$artnr</font><font color="#007700">] == </font><font color="#0000BB">$num</font><font color="#007700">) {<br /> unset(</font><font color="#0000BB">$this</font><font color="#007700">-></font><font color="#0000BB">items</font><font color="#007700">[</font><font color="#0000BB">$artnr</font><font color="#007700">]);<br /> return </font><font color="#0000BB">true</font><font color="#007700">;<br /> } else {<br /> return </font><font color="#0000BB">false</font><font color="#007700">;<br /> }<br /> }<br />}<br /></font><font color="#0000BB">?></font> </font> </code></TD ></TR ></TABLE ><P ></P ></DIV > </P ><P > 上面的例子定义了一个 Cart 类,这个类由购物车中的商品构成的数组和两个用于从购物车中添加和删除商品的函数组成。 </P ><DIV CLASS="warning" ><P ></P ><TABLE CLASS="warning" BORDER="1" WIDTH="100%" ><TR ><TD ALIGN="CENTER" ><B >警告</B ></TD ></TR ><TR ><TD ALIGN="LEFT" ><P > <SPAN CLASS="emphasis" ><I CLASS="emphasis" >不能</I ></SPAN >将一个类的定义分割到多个文件中。也<SPAN CLASS="emphasis" ><I CLASS="emphasis" >不能</I ></SPAN >将一个类的定义分割到多个 PHP 块中,除非该分割是在一个方法声明内部。以下用法将不起作用: </P ><P > <DIV CLASS="informalexample" ><P ></P ><A NAME="AEN5462" ></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">test </font><font color="#007700">{<br /></font><font color="#0000BB">?><br /><?php<br /> </font><font color="#007700">function </font><font color="#0000BB">test</font><font color="#007700">() {<br /> print </font><font color="#DD0000">'OK'</font><font color="#007700">;<br /> }<br />}<br /></font><font color="#0000BB">?></font> </font> </code></TD ></TR ></TABLE ><P ></P ></DIV > </P ><P > 但是以下用法是可以的: </P ><P > <DIV CLASS="informalexample" ><P ></P ><A NAME="AEN5466" ></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">test </font><font color="#007700">{<br /> function </font><font color="#0000BB">test</font><font color="#007700">() {<br /> </font><font color="#0000BB">?><br /></font> <font color="#0000BB"><?php<br /> </font><font color="#007700">print </font><font color="#DD0000">'OK'</font><font color="#007700">;<br /> }<br />}<br /></font><font color="#0000BB">?></font> </font> </code></TD ></TR ></TABLE ><P ></P ></DIV > </P ></TD ></TR ></TABLE ></DIV ><P > 以下警告仅用于 PHP 4。 </P ><DIV CLASS="caution" ><P ></P ><TABLE CLASS="caution" BORDER="1" WIDTH="100%" ><TR ><TD ALIGN="CENTER" ><B >小心</B ></TD ></TR ><TR ><TD ALIGN="LEFT" ><P > 名称 <TT CLASS="literal" >stdClass</TT > 已经被 Zend 使用并保留。不能在 PHP 代码中定义名为 <TT CLASS="literal" >stdClass</TT > 的类。 </P ></TD ></TR ></TABLE ></DIV ><DIV CLASS="caution" ><P ></P ><TABLE CLASS="caution" BORDER="1" WIDTH="100%" ><TR ><TD ALIGN="CENTER" ><B >小心</B ></TD ></TR ><TR ><TD ALIGN="LEFT" ><P > 函数名 <TT CLASS="literal" >__sleep</TT > 和 <TT CLASS="literal" >__wakeup</TT > 在 PHP 类中是魔术函数。除非想要与之联系的魔术功能,否则在任何类中都不能以此命名函数。 </P ></TD ></TR ></TABLE ></DIV ><DIV CLASS="caution" ><P ></P ><TABLE CLASS="caution" BORDER="1" WIDTH="100%" ><TR ><TD ALIGN="CENTER" ><B >小心</B ></TD ></TR ><TR ><TD ALIGN="LEFT" ><P > PHP 将所有以 __ 开头的函数名保留为魔术函数。除非想要使用一些见于文档中的魔术功能,否则建议不要在 PHP 中将函数名以 __ 开头。 </P ></TD ></TR ></TABLE ></DIV ><P > 在 PHP 4 中,<TT CLASS="literal" >var</TT > 变量的值只能初始化为常量。用非常量值初始化变量,需要一个初始化函数,该函数在对象被创建时自动被调用。这样一个函数被称之为构造函数(见下面)。 </P ><DIV CLASS="informalexample" ><P ></P ><A NAME="AEN5481" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" CELLPADDING="5" ><TR ><TD ><code><font color="#000000"> <font color="#0000BB"><?php<br /></font><font color="#FF8000">/* PHP 4 中不能这样用 */<br /></font><font color="#007700">class </font><font color="#0000BB">Cart </font><font color="#007700">{<br /> var </font><font color="#0000BB">$todays_date </font><font color="#007700">= </font><font color="#0000BB">date</font><font color="#007700">(</font><font color="#DD0000">"Y-m-d"</font><font color="#007700">);<br /> var </font><font color="#0000BB">$name </font><font color="#007700">= </font><font color="#0000BB">$firstname</font><font color="#007700">;<br /> var </font><font color="#0000BB">$owner </font><font color="#007700">= </font><font color="#DD0000">'Fred ' </font><font color="#007700">. </font><font color="#DD0000">'Jones'</font><font color="#007700">;<br /> </font><font color="#FF8000">/* 不过包含有常量的数组可以 */<br /> </font><font color="#007700">var </font><font color="#0000BB">$items </font><font color="#007700">= array(</font><font color="#DD0000">"VCR"</font><font color="#007700">, </font><font color="#DD0000">"TV"</font><font color="#007700">);<br />}<br /><br /></font><font color="#FF8000">/* 应该这样进行 */<br /></font><font color="#007700">class </font><font color="#0000BB">Cart </font><font color="#007700">{<br /> var </font><font color="#0000BB">$todays_date</font><font color="#007700">;<br /> var </font><font color="#0000BB">$name</font><font color="#007700">;<br /> var </font><font color="#0000BB">$owner</font><font color="#007700">;<br /> var </font><font color="#0000BB">$items </font><font color="#007700">= array(</font><font color="#DD0000">"VCR"</font><font color="#007700">, </font><font color="#DD0000">"TV"</font><font color="#007700">);<br /> function </font><font color="#0000BB">Cart</font><font color="#007700">() {<br /> </font><font color="#0000BB">$this</font><font color="#007700">-></font><font color="#0000BB">todays_date </font><font color="#007700">= </font><font color="#0000BB">date</font><font color="#007700">(</font><font color="#DD0000">"Y-m-d"</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">$GLOBALS</font><font color="#007700">[</font><font color="#DD0000">'firstname'</font><font color="#007700">];<br /> </font><font color="#FF8000">/* etc. . . */<br /> </font><font color="#007700">}<br />}<br /></font><font color="#0000BB">?></font> </font> </code></TD ></TR ></TABLE ><P ></P ></DIV ><P > 类也是一种类型,就是说,它们是实际变量的蓝图。必须用 <TT CLASS="literal" >new</TT > 运算符来创建相应类型的变量。 </P ><DIV CLASS="informalexample" ><P ></P ><A NAME="AEN5485" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" CELLPADDING="5" ><TR ><TD ><code><font color="#000000"> <font color="#0000BB"><?php<br />$cart </font><font color="#007700">= new </font><font color="#0000BB">Cart</font><font color="#007700">;<br /></font><font color="#0000BB">$cart</font><font color="#007700">-></font><font color="#0000BB">add_item</font><font color="#007700">(</font><font color="#DD0000">"10"</font><font color="#007700">, </font><font color="#0000BB">1</font><font color="#007700">);<br /><br /></font><font color="#0000BB">$another_cart </font><font color="#007700">= new </font><font color="#0000BB">Cart</font><font color="#007700">;<br /></font><font color="#0000BB">$another_cart</font><font color="#007700">-></font><font color="#0000BB">add_item</font><font color="#007700">(</font><font color="#DD0000">"0815"</font><font color="#007700">, </font><font color="#0000BB">3</font><font color="#007700">);<br /></font><font color="#0000BB">?></font> </font> </code></TD ></TR ></TABLE ><P ></P ></DIV ><P > 上述代码创建了两个 Cart 类的对象 <CODE CLASS="varname" >$cart</CODE > 和 <CODE CLASS="varname" >$another_cart</CODE >,对象 <CODE CLASS="varname" >$cart</CODE > 的方法 add_item() 被调用时,添加了 1 件 10 号商品。对于对象 <CODE CLASS="varname" >$another_cart</CODE >,3 件 0815 号商品被添加到购物车中。 </P ><P > <CODE CLASS="varname" >$cart</CODE > 和 <CODE CLASS="varname" >$another_cart</CODE > 都有方法 add_item(),remove_item() 和一个 items 变量。它们都是明显的函数和变量。可以把它们当作文件系统中的某些类似目录的东西来考虑。在文件系统中,可以拥有两个不同的 <TT CLASS="filename" >README.TXT</TT > 文件,只要不在相同的目录中。正如从为了根目录访问每个文件需要输入该文件的完整的路径名一样,必须指定需要调用的函数的完整名称:在 PHP 术语中,根目录将是全局名字空间,路径名符号将是 <TT CLASS="literal" >-></TT >。因而,名称 <CODE CLASS="varname" >$cart->items</CODE > 和 <CODE CLASS="varname" >$another_cart->items</CODE > 命名了两个不同的变量。注意变量名为 <CODE CLASS="varname" >$cart->items</CODE >,不是 <CODE CLASS="varname" >$cart->$items</CODE >,那是因为在 PHP 中一个变量名只有一个单独的美元符号。 </P ><DIV CLASS="informalexample" ><P ></P ><A NAME="AEN5501" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" CELLPADDING="5" ><TR ><TD ><code><font color="#000000"> <font color="#0000BB"><?php<br /></font><font color="#FF8000">// 正确,只有一个 $<br /></font><font color="#0000BB">$cart</font><font color="#007700">-></font><font color="#0000BB">items </font><font color="#007700">= array(</font><font color="#DD0000">"10" </font><font color="#007700">=> </font><font color="#0000BB">1</font><font color="#007700">);<br /><br /></font><font color="#FF8000">// 不正确,因为 $cart->$items 变成了 $cart->""<br /></font><font color="#0000BB">$cart</font><font color="#007700">-></font><font color="#0000BB">$items </font><font color="#007700">= array(</font><font color="#DD0000">"10" </font><font color="#007700">=> </font><font color="#0000BB">1</font><font color="#007700">);<br /><br /></font><font color="#FF8000">// 正确,但可能不是想要的结果:<br />// $cart->$myvar 变成了 $cart->items<br /></font><font color="#0000BB">$myvar </font><font color="#007700">= </font><font color="#DD0000">'items'</font><font color="#007700">;<br /></font><font color="#0000BB">$cart</font><font color="#007700">-></font><font color="#0000BB">$myvar </font><font color="#007700">= array(</font><font color="#DD0000">"10" </font><font color="#007700">=> </font><font color="#0000BB">1</font><font color="#007700">);<br /></font><font color="#0000BB">?></font> </font> </code></TD ></TR ></TABLE ><P ></P ></DIV ><P > 在定义类的时候,无法得知将使什么名字的对象来访问:在编写 Cart 类时,并不知道之后对象的名称将会命名为 <CODE CLASS="varname" >$cart</CODE > 或者 <CODE CLASS="varname" >$another_cart</CODE >。因而你不能在类中使用 <CODE CLASS="varname" >$cart->items</CODE >。然而为了类定义的内部访问自身的函数和变量,可以使用伪变量 <CODE CLASS="varname" >$this</CODE > 来达到这个目的。<CODE CLASS="varname" >$this</CODE > 变量可以理解为“我自己的”或者“当前对象”。因而 '<CODE CLASS="varname" >$this->items[$artnr]</CODE > += <CODE CLASS="varname" >$num</CODE >' 可以理解为“我自己的物品数组的 <CODE CLASS="varname" >$artnr</CODE > 计数器加 <CODE CLASS="varname" >$num</CODE >”或者“在当前对象的物品数组的 <CODE CLASS="varname" >$artnr</CODE > 计数器加 <CODE CLASS="varname" >$num</CODE >”。 </P ><DIV CLASS="note" ><BLOCKQUOTE CLASS="note" ><P ><B >注意: </B > 伪变量 <CODE CLASS="varname" >$this</CODE > 通常未定义,如果其所在的方法是被静态调用的话。但这不是个严格规定:如果一个方法被从另一个对象内静态调用的话,则 <CODE CLASS="varname" >$this</CODE > 会被定义。此时 <CODE CLASS="varname" >$this</CODE > 的值是那个发出调用的对象。用下例演示: <DIV CLASS="informalexample" ><P ></P ><A NAME="AEN5520" ></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<br /></font><font color="#007700">{<br /> function </font><font color="#0000BB">foo</font><font color="#007700">()<br /> {<br /> if (isset(</font><font color="#0000BB">$this</font><font color="#007700">)) {<br /> echo </font><font color="#DD0000">'$this is defined ('</font><font color="#007700">;<br /> echo </font><font color="#0000BB">get_class</font><font color="#007700">(</font><font color="#0000BB">$this</font><font color="#007700">);<br /> echo </font><font color="#DD0000">")\n"</font><font color="#007700">;<br /> } else {<br /> echo </font><font color="#DD0000">"\$this is not defined.\n"</font><font color="#007700">;<br /> }<br /> }<br />}<br /><br />class </font><font color="#0000BB">B<br /></font><font color="#007700">{<br /> function </font><font color="#0000BB">bar</font><font color="#007700">()<br /> {<br /> </font><font color="#0000BB">A</font><font color="#007700">::</font><font color="#0000BB">foo</font><font color="#007700">();<br /> }<br />}<br /><br /></font><font color="#0000BB">$a </font><font color="#007700">= new </font><font color="#0000BB">A</font><font color="#007700">();<br /></font><font color="#0000BB">$a</font><font color="#007700">-></font><font color="#0000BB">foo</font><font color="#007700">();<br /></font><font color="#0000BB">A</font><font color="#007700">::</font><font color="#0000BB">foo</font><font color="#007700">();<br /></font><font color="#0000BB">$b </font><font color="#007700">= new </font><font color="#0000BB">B</font><font color="#007700">();<br /></font><font color="#0000BB">$b</font><font color="#007700">-></font><font color="#0000BB">bar</font><font color="#007700">();<br /></font><font color="#0000BB">B</font><font color="#007700">::</font><font color="#0000BB">bar</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" >$this is defined (a) $this is not defined. $this is defined (b) $this is not defined.</PRE ></TD ></TR ></TABLE ><P ></P ></DIV > </P ></BLOCKQUOTE ></DIV ><DIV CLASS="note" ><BLOCKQUOTE CLASS="note" ><P ><B >注意: </B > 有一些不错的函数用来处理类和对象。应该关注一下<A HREF="ref.classobj.html" >类/对象函数</A >。 </P ></BLOCKQUOTE ></DIV ></DIV ></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="functions.internal.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="keyword.extends.html" ACCESSKEY="N" >下一页</A ></TD ></TR ><TR ><TD WIDTH="33%" ALIGN="left" VALIGN="top" >内部(内置)函数</TD ><TD WIDTH="34%" ALIGN="center" VALIGN="top" ><A HREF="langref.html" ACCESSKEY="U" >上一级</A ></TD ><TD WIDTH="33%" ALIGN="right" VALIGN="top" ><TT CLASS="literal" >继承</TT ></TD ></TR ></TABLE ></DIV ></BODY ></HTML >