__clone 魔术方法 -- 深度克隆对象
有时可能需要根据一个对象完全克隆出一个一模一样的对象,而且克隆以后,两个对象互不干扰。
格式:
$obj = new Class();
$objcopy = clone $obj;
魔术方法: __clone()
当执行 clone 克隆时会自动调用的方法,主要用于解决对象中特殊属性的复制操作。
用“=”赋值实例,实际上时引用赋值,改变其中一个的值,另一个实例也会被改变。如下面的栗子
class person{ public $name; } $m1 = new person(); $m1->name = 'zhangsan'; $m2 = $m1; $m2->name = 'lisi'; echo $m1->name.'<br>'; //输出结果 lisi ,在给m2设置值时$m1的值也被改变
因为 $m1 和 $m2 都是指向同一个内存区的引用,所以修改一个对象,另外一个也会同时会被修改。
为了让复制的对象跟之前对象没有任何关系,我们要用到PHP的clone操作:
1.浅克隆
使用PHP的clone操作复制对象,可以实现克隆。如下面栗子:
class person1{ public $name; } $m3 = new person1(); $m3->name = 'zhangsan'; $m4 = clone $m3; $m4->name = 'lisi'; echo $m3->name.'<br>'; //输出结果 zhangsan echo $m4->name.'<br>'; //输出结果 lisi
以上是浅克隆,只能做基本的克隆操作,如果对象的成员属性本身就是refence类型(引用),clone之后这些成员并没有被真正复制,如下面的栗子:
class person2{ public $name; } $a = 'zhangsan'; $m5 = new person2(); $m5->name = &$a; $m6 = clone $m5; $m6->name = 'lisi'; echo $m5->name.'<br>'; //输出结果 lisi class stu{ public $grade; public $student; public function __construct(){ $this->student = new person2(); } } $m7 = new stu(); $m7->student->name = 'xiaoming'; $m8 = clone $m7; $m8->student->name = 'lili'; echo $m7->student->name.'<br>'; //输出 lili
2.深克隆
在类中使用魔术方法 __clone 实现对象的深度克隆。
class person3{ public $name; } class stu{ public $grade; public $student; public function __construct(){ $this->student = new person2(); } public function __clone(){ $this->student = clone $this->student; } } $m7 = new stu(); $m7->student->name = 'xiaoming'; $m8 = clone $m7; $m8->student->name = 'lili'; echo $m7->student->name.'<br>'; //输出 xiaoming
__tostring() 魔术方法 -- 直接输出一个对象时自动调用
魔术方法“__toString()”是快速获取对象的字符串表示的最快捷方式。即当我们直接要输出一个对象时,如echo $a,print $a,那么会自动调用的此魔术方法。
注意: __toString()方法必须返回一个字符串类型的值。
class person{ public $name; public $age; public function __construct($name,$age){ $this->name = $name; $this->age = $age; } public function __tostring(){ echo 'I am '.$this->name.', now '.$this->age.' years.<br>'; } } $p = new person('lisi',15); echo $p; //输出结果 I am lisi, now 15 years.
__call() 魔术方法 -- 访问不存在的方法时自动调用
当试图调用一个对象中不存在的方法时,就会产生错误。PHP提供了__call() 这个方法来处理这种情况。即当调用一个不可访问方法(如未定义,或者不可见)时,__call() 会被调用。
格式: mixed __call(string $name, array $arguments)
说明: 第一个参数:$name表示方法名 第二个参数:$arguments表示调用时的参数列表(数组格式)
class person{ public function __call($name,$ags){ echo 'Function '.$name.' not exsit<br>'; var_dump($ags); } } $p = new person(); $p->test('lisi',20); //输出 Function test not exsit array(2) { [0]=> string(4) "lisi" [1]=> int(20) }
__autoload()魔术方法 -- new 实例化一个不存在的类时自动调用
PHP5 中当 new 实例化一个不存在的类时,则自动调用此函数__autoload(),并将类名作为参数传入此函数。可以使用这个实现类的自动加载。
PHP在魔术函数__autoload()方法出现以前,如果你要在一个程序文件中实例化100个对象,那么你必须用include或者require包含进来100个类文件,或者你把这100个类定义在同一个类文件中——相信这个文件一定会非常大。
但是__autoload()方法出来了,以后就不必为此大伤脑筋了,这个类会在你实例化对象之前自动加载制定的文件。
下边我们通过一个例子来看一下,具体的使用方法,并在稍后说明使用PHP魔术函数__autoload应该注意些什么。
function __autoload($classname){ $classpath = './'.$classname.'.php'; if(file_exists($classpath)){ require_once($classpath); }else{ echo 'class file '.$calsspath.' not found!'; } } class classB extends classA{ public function say(){ echo 'I am '.$this->name; } } $c = new classB('lisi'); echo $c->say(); //输出 I am lisi
这个文件的运行是一点问题都没有的,可见autoload是多么的好用啊,呵呵……
但是不得不提醒你一下几个方面是必须要注意的。
1、如果类存在继承关系(例如:ClassB extends ClassA),并且ClassA不在ClassB所在目录
利用__autoload魔术函数实例化ClassB的时候就会受到一个致命错误:
代码如下 复制代码
Fatal error: Class ‘Classd’ not found in ……ClassB.php on line 2,
解决方法:把所有存在extends关系的类放在同一个文件目录下,或者在实例化一个继承类的时候在文件中手工包含被继承的类;
2、另外一个需要注意的是,类名和类的文件名必须一致,才能更方便的使用魔术函数__autoload;