关键字clone
使用clone
会复制出一个新的对象。
class c1 {
public $a1;
public $a2;
}
$c1 = new c1;
$c1 -> a1 = 'a';
$c1 -> a2 = 'b';
$copy_c1 = $c1;
/*对象的赋值是引用赋值,$copy_c1与$c1指向的是同一地址*/
$clone_c1 = clone $c1;
/*clone会复制出一个新对象*/
echo "<span style='white-space:pre;'>";
var_dump($c1);
var_dump($copy_c1);
var_dump($clone_c1);
输出结果:
object(c1)#1 (2) {
["a1"]=>
string(1) "a"
["a2"]=>
string(1) "b"
}
object(c1)#1 (2) {
["a1"]=>
string(1) "a"
["a2"]=>
string(1) "b"
}
object(c1)#2 (2) {
["a1"]=>
string(1) "a"
["a2"]=>
string(1) "b"
}
继续添加代码:
$c1 -> a1 = 'c';
var_dump($c1);
var_dump($copy_c1);
var_dump($clone_c1);
输出结果:
object(c1)#1 (2) {
["a1"]=>
string(1) "c"
["a2"]=>
string(1) "b"
}
object(c1)#1 (2) {
["a1"]=>
string(1) "c"
["a2"]=>
string(1) "b"
}
object(c1)#2 (2) {
["a1"]=>
string(1) "a"
["a2"]=>
string(1) "b"
}
得出结论:实例化对象赋值为引用赋值,使用关键字clone
可以完成对对象的复制得到新的独立的对象。
clone
方法
使用关键字 clone
克隆一个对象,新创建的对象复制生成的对象中的 __clone()
方法会被调用
class c1 {
public $a1;
public $a2;
public function __clone() {
$this -> a1 = 'x';
}
}
$c1 = new c1;
$c1 -> a1 = 'a';
$c1 -> a2 = 'b';
var_dump($c1);
$c2 = clone $c1;
var_dump($c2);
打印结果:
object(c1)#1 (2) {
["a1"]=>
string(1) "a"
["a2"]=>
string(1) "b"
}
object(c1)#2 (2) {
["a1"]=>
string(1) "x"
["a2"]=>
string(1) "b"
}
浅复制与深复制
class nc {
public $na = 'm';
}
class tc {
public $a1;
public $a2;
}
$obj = new tc;
$obj -> a1 = 'a';
$obj -> a2 = new nc;
echo "<span style='white-space:pre'>";
var_dump($obj);
$copy_obj_new = clone $obj;
var_dump($copy_obj_new);
$copy_obj_new->a1='b';
$copy_obj_new->a2->na='n';
var_dump($copy_obj_new);
var_dump($obj);
输出:
object(tc)#1 (2) {
["a1"]=>
string(1) "a"
["a2"]=>
object(nc)#2 (1) {
["na"]=>
string(1) "m"
}
}
object(tc)#3 (2) {
["a1"]=>
string(1) "a"
["a2"]=>
object(nc)#2 (1) {
["na"]=>
string(1) "m"
}
}
object(tc)#3 (2) {
["a1"]=>
string(1) "b"
["a2"]=>
object(nc)#2 (1) {
["na"]=>
string(1) "n"
}
}
object(tc)#1 (2) {
["a1"]=>
string(1) "a"
["a2"]=>
object(nc)#2 (1) {
["na"]=>
string(1) "n"
}
}
结论:clone
后属性值为非对象时,克隆前后是独立的,没有相互影响。属性值为对象时,对象的属性值仍然指向同一个变量的地址。
解决浅复制
一种是使用__clone()
方法此法不推荐,因为不适合批量操作,另一种是序列与反序列
clone
class nc {
public $na = 'm';
}
class tc {
public $a1;
public $a2;
public function __clone(){
$this->a2=clone new nc;
}
}
$tc=new tc;
$tc->a1='a';
$tc->a2=new nc;
var_dump($tc);
var_dump(clone $tc);
输出结果:
object(tc)#1 (2) { ["a1"]=> string(1) "a" ["a2"]=> object(nc)#2 (1) { ["na"]=> string(1) "m" } } object(tc)#3 (2) { ["a1"]=> string(1) "a" ["a2"]=> object(nc)#5 (1) { ["na"]=> string(1) "m" } }
注意:产生#5
而不是#4
的原因是new classname
生成#4
,clone new classname
便生成#5
serialize/unserialize
class newClass {
public $newAttr = 'm';
}
class testClass {
public $attr1;
public $attr2;
}
$obj = new testClass();
$obj->attr1='a';
$obj->attr2=new newClass;
echo "<span style='white-space:pre'>";
var_dump($obj);
$newc=unserialize(serialize($obj));
var_dump($newc);
输出结果:
object(testClass)#1 (2) {
["attr1"]=>
string(1) "a"
["attr2"]=>
object(newClass)#2 (1) {
["newAttr"]=>
string(1) "m"
}
}
object(testClass)#3 (2) {
["attr1"]=>
string(1) "a"
["attr2"]=>
object(newClass)#4 (1) {
["newAttr"]=>
string(1) "m"
}
}
注意:unserialize
产生的新的对象对应的地址是#3
和#4
,而不是#3
,#5
。