本节将学习一下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);
?>
其中就做了一次深拷贝。


