本节将学习一下PHP的clone。顾名思义,clone主要是完成php对象的复制的。那么在使用clone这个操作的时候,我们应该注意点什么 呢?本人是一个c++程序员,对于c++中类的操作比较了解,其中c++中有构造函数,析构函数,拷贝构造函数等等,这些函数将在对象的各种阶段自动调 用。我觉得clone有点类似于c++中的拷贝构造函数,只不过,c++的拷贝构造函数是在赋值的时候自动调用,但是php的拷贝构造函数实在clone 的时候调用。
先看一下下面的代码:
<?php class testClass{ public $_name = "ZMAX"; } $objA = new testClass(); $objB = $objA; //执行一个复制 $objC = clone $objA;//clone一个对象 echo "objA Name:".$objA->_name."<br/>"; echo "objB Name:".$objB->_name."<br/>"; echo "objC Name:".$objC->_name."<br/>"; $objB->_name="ZMAX 99"; echo "objA Name:".$objA->_name."<br/>"; echo "objB Name:".$objB->_name."<br/>"; echo "objC Name:".$objC->_name."<br/>"; ?>
上面的代码的执行结果如下:
objA Name:ZMAX
objB Name:ZMAX
objC Name:ZMAX
objA Name:ZMAX 99
objB Name:ZMAX 99
objC Name:ZMAX
其中对象B是复制的,对象C是clone的。我们可以发现,对象B变得时候,对象A也改变了,但是对象C并没有变。这里就说明了。PHP的赋值操作默认是引用。而clone是内存拷贝。
php5以后对象赋值默认就是引用了,php4要加上&
上面的代码,简单的说明了一下clone的用法。下面是比较完整的关于clone的描述。
对象的复制
在多数情况下,我们并不需要完全复制一个对象来获得其中属性。但是有一个情况下的确需要:如果你有一个GTK窗口对象,该对象持有窗口相关的资源。你可能会想到复制一个新的窗口,保持所有属性同原先的窗口相同,但是必须是一个新的对象(因为,如果不是新的对象,那么一个窗口中的改变会影响到另一个窗口)。还有一种情况:如果对象A中保存对象B的引用,当你复制对象A时,你想其中使用的对象不再是对象B而是B的一个副本,那么你必须得到对象A的一个副本。
对象复制可以通过clone关键字来完成(如果可能,这将调用对象的__clone()方法)。对象中的__clone()方法不能直接调用。你可以用
$copy_of_object = clone $object;
当对象被复制后,PHP5会对对象的所有属性执行一个浅拷贝。所有的引用属性仍然会指向原来的变量的引用。
void __clone(void)
当复制完成时,如果定义了__clone()方法,则新创建的对象中的__clone()方法会被调用。可用于修改属性的值。
看下面的代码:
<?php class Account { public $balance; public function __construct($balance) { $this->balance = $balance; } } class Person { private $id; private $name; private $age; public $account; public function __construct($name, $age, Account $account) { $this->name = $name; $this->age = $age; $this->account = $account; } public function setId($id) { $this->id = $id; } public function __clone() { #复制方法,可在里面定义再clone是进行的操作 $this->id = 0; $this->account = clone $this->account; #不加这一句,account在clone是会只被复制引用,其中一个account的balance被修改另一个也同样会被修改 } } $person = new Person("peter", 15, new Account(1000)); $person->setId(1); $person2 = clone $person; $person2->account->balance = 250; var_dump($person, $person2); ?>
其中就做了一次深拷贝。