14.2.7 PHP中一些和类有关的函数
本节介绍一些和类有关的PHP函数,这些函数在PHP中被称为Magic Methods,因为它们在PHP是比较特别的,使用它们可以完成很多功能。这些函数如下所示。
❑__construct():构造函数,当实例化一个类对象时调用。
❑__destruct():析构函数,当一个对象不再使用时调用。
❑__get():当访问某个类没有显示定义的属性时,该函数被调用。
❑__set():当设置一个不存在的属性时,该函数被调用。
❑__call():当访问一个不存在的方法时,该函数被调用。
❑__toString():将一个对象转换成字符串。
❑__clone():克隆一个对象时使用。
注意 这些函数均以双下划线开头。
前面已经介绍过构造函数__construct()和析构函数__destruct()的用法,下面简单介绍一下其他几个函数的用法。
在PHP中,每一个类都会自动继承__set()和__get()方法,它们的定义如下所示。
void__set(string$name,mixed$value)
mixed__get(string$name)
当程序访问当前类没有显示定义的属性时,被访问的属性名称作为参数传入相应的方法。PHP中任何类都可以定义(即重写)各自__set()和__get()方法,以实现需要的功能。代码14-6演示了这两个函数的用法。
代码14-6 在PHP中实现__set()和__get()方法14-6.php
01 <?php
02 class Test
03 {
04 public function__get($prop_name)__//get()方法
05 {
06 echo"获取属性:($prop_namen)<br/>";
07 }
08 public function__set($prop_name,$value)//set()方法
09 {
10 echo"设置属性$prop_name的值为'$value'";
11 }
12 }
13
14 $test=new Test();
15 $test->Name;//对象$test访问一个不存在的属性Name,此时调用方法__get()
16 $test->Name="测试设置";//对象$test为一个不存在的属性Name设置值,此时会调用__set()方法
17 ?>
【代码解析】这段代码中,创建类时,没有定义任何属性。Test类重写了方法__get()和__set(),为了说明其用法,重写这两个函数时只是向页面输出了一些信息,并没有做更复杂的操作。图14-4是代码14-6的执行结果。
从这个执行结果可以看出,在程序访问一个不存在的属性Name时,方法__get()会被调用,如代码第15行所示。该方法向页面输出一段信息,包含有所要取得的属性,但因为这个属性没有定义过,因此输出到页面的信息会有一段空白。当程序为一个不存在的属性Name赋值时,会调用__set()方法,同样地,该方法会创建一个属性Name,并为其赋值为'测试设置'。也向页面输出一段信息,这段信息里包含了所创建的属性名称及其值,它们是由参数传入__set()函数的。
方法__toString()的作用是,当需要输出一个对象时,程序通过重写方法__toString()将对象转换成字符串。代码14-7演示了该函数的用法。
代码14-7 在PHP程序中使用__toString()方法14-7.php
01 <?php
02 class Student
03 {
04 private$id,$name;//成员变量
05
06 public function__construct($s_id,$s_name)//构造函数
07 {
08 $this->id=$s_id;
09 $this->name=$s_name;
10 }
11 public function__toString()//__toString()方法
12 {
13 return"$this->id:$this->name";
14 }
15 }
16 $stu=new Student(1,'George Wesley');
17
18 echo'<b>以下输出对象时,实际调用了方法__toString()</b><br/><br/>';
19 echo$stu
20 ?>
【代码解析】第11~14行定义了__toString()方法,虽然在第19行的代码中看不到__toString()的踪迹,但实际上输出对象就是调用__toString()将对象转化为字符串。代码14-7的执行结果如图14-5所示。
在本节最开始的部分,讲述过PHP5中默认通过引用传递对象。假设,$obj1和$obj2是两个对象,使用$obj2=$obj1这样的方法复制出的对象是相互关联的。如果在程序中需要复制出一个值与原来相同的对象,但又不希望目标对象与源对象关联,那么就需要使用clone关键字,像这样:$obj2=clone$obj1。如果还希望在复制的同时,目标对象中的某些属性与源对象不同,可以在类中定义一个__clone()方法,在这个方法中完成为目标对象的属性赋以新值。代码14-7演示了如何使用__clone()。
代码14-8 在PHP程序中使用__clone()方法14-8.php
01 <?php
02 class doClone
03 {
04 private$id,$name,$address;
05
06 public function__construct($id=0,$name='',$address='')//构造函数
07 {
08 $this->id=$id;
09 $this->name=$name;
10 $this->address=$address;
11 }
12 public function get_id()//成员函数get_id()
13 {
14 return$this->id;
15 }
16 public function get_name()//成员函数get_name()
17 {
18 return$this->name;
19 }
20 public function get_address()//成员函数get_address()
21 {
22 return$this->address;
23 }
24 public function__clone()//__clone()方法
25 {
26 $this->id=$this->id+1;
27 $this->name='Kong';
28 $this->address="America";
29 }
30 }
31
32 $cle=new doClone(99,'King','Island');
33 echo'<b>clone之前,对象$cle的属性:</b>';
34 echo'<br/>';
35 echo'id='.$cle->get_id()."<br/>";
36 echo'name='.$cle->get_name()."<br/>";
37 echo'address='.$cle->get_address();
38 echo'<br/>';
39 echo'<br/>';
40
41 $cle_cloned=clone$cle;
42 echo'<b>clone之后,对象$cle的属性:</b>';
43 echo'<br/>';
44 echo'id='.$cle->get_id()."<br/>";
45 echo'name='.$cle->get_name()."<br/>";
46 echo'address='.$cle->get_address();
47 echo'<br/>';
48 echo'<br/>';
49
50 echo'<b>clone之后,对象$cle_cloned的属性:</b>';
51 echo'<br/>';
52 echo'id='.$cle_cloned->get_id()."<br/>";
53 echo'name='.$cle_cloned->get_name()."<br/>";
54 echo'address='.$cle_cloned->get_address();
55 ?>
【代码解析】这段代码的执行结果如图14-6所示。从执行结果可以看出,使用了clone之后,复制出的对象的属性在__clone方法中重新设置,并且源对象$cle和目标对象$cle_cloned之间不再有什么关系。
提示 方法__call()会在PHP程序访问一个不存在的方法时被调用。该函数用法类似__get()和__set(),这里不再赘述。