php引用复制,浅复制clone和深复制
1.引用复制
<?php class a { public $info=0; } $a=new a(); $b=$a; //引用赋值 $a->info="10"; echo $a->info."<br>"; echo $b->info."<br>"; die;
结果如下:
2.浅复制clone
<?php class a { public $info=0; } $a=new a(); $b=clone $a; //clone $a->info="10"; echo $a->info."<br>"; echo $b->info."<br>"; die;
结果如下
那么为什么叫浅复制呢,因为它只能复制类里面的属性和方法,如果类里面的属性和方法用到的其他的对象,那么复制过去的也是引用复制,如下:
<?php class mybianliang { public $bianliagn=0; public function __construct($bianliang){ $this->bianliang=$bianliang; } public function changebianliang($bianliang2){ $this->bianliang=$bianliang2; } } class mytest { public $test=0; public function __construct($bianliang){ $this->test=new mybianliang($bianliang); } } $a=new mytest(10); $b= clone $a; //clone echo $a->test->bianliang."<br>"; $a->test->changebianliang(20); //改变a对象中test对象中的属性值,看看b对象中的test对象中的属性可有变化 echo $b->test->bianliang."<br>"; die;
结果如下:
这说明 $b对象中的$test对象指向的是$a对象的$test对象,那么如何避免呢
用__clone魔术方法把类中用的其他对象重新clone一下
<?php class mybianliang { public $bianliagn=0; public function __construct($bianliang){ $this->bianliang=$bianliang; } public function changebianliang($bianliang2){ $this->bianliang=$bianliang2; } } class mytest { public $test=0; public function __construct($bianliang){ $this->test=new mybianliang($bianliang); } public function __clone(){ $this->test=clone $this->test; //克隆一下这个对象,不然指向的还是同一个对象 } } $a=new mytest(10); $b= clone $a; //clone echo $a->test->bianliang."<br>"; $a->test->changebianliang(20); //改变a对象中test对象中的属性值,看看b对象中的test对象可有变化 echo $b->test->bianliang."<br>"; die;
结果如下
3.深复制
深复制,可以利用上面的魔术方法__clone()或者利用序列化和反序列化的方法
<?php class mybianliang { public $bianliagn=0; public function __construct($bianliang){ $this->bianliang=$bianliang; } public function changebianliang($bianliang2){ $this->bianliang=$bianliang2; } } class mytest { public $test=0; public function __construct($bianliang){ $this->test=new mybianliang($bianliang); } } $a=new mytest(10); $b = unserialize(serialize($a)); //序列化和反序列化 echo $a->test->bianliang."<br>"; $a->test->changebianliang(20); //改变a对象中test对象中的属性值,看看b对象中的test对象可有变化 echo $b->test->bianliang."<br>"; die;
执行结果