当在使用某个对象,而需要对该对象进行大量操作,或者在新的上下文环境中复用该对象的部分或全部数据时,需要对其进行拷贝操作。
那么结合代码来看看从浅拷贝到深拷贝发生了什么
<?php class People { protected $_name = '张三'; protected $_sex = '男'; protected $_age = '18'; /** * return Name */ public function getName() { return $this-> _name; } /** * set name */ public function setName($name) { $this->_name = (string)$name; return $this; } } $p1 = new People(); $p2 = $p1; 复制代码
上面创建了一个people类,然后实例化了p1,用赋值的方式 创建了p2 这样就得到了两个名字,年龄,性别都一样的人。那么当我们修改p1或p2时都会改变name
echo $p1->getName(); echo $p2->getName(); //p2改名 $p2->setName('李四'); echo $p1->getName(); echo $p2->getName(); //p1改名 $p1->setName('王五'); echo $p1->getName(); echo $p2->getName(); 复制代码
输出为:张三张三李四李四王五王五
这里对象的赋值和传值都是以引用的方式。名字虽然不同但指的是同一个人。所以这种拷贝相当于一个人有个名字和外号,人还是这个人,这种拷贝不是我所想要的。那么换种方式。用clone来复制对象。
$p1 = new People(); $p2 = clone $p1; echo $p1->getName(); echo $p2->getName(); //p2改名 $p2->setName('李四'); echo $p1->getName(); echo $p2->getName(); //p1改名 $p1->setName('王五'); echo $p1->getName(); echo $p2->getName(); 复制代码
那么这段代码用clone关键字复制p1对象,现在这个p1对象得到了这个真正的拷贝p2,p1和p2改名时分别都能改成功,而p1和p2都属于不同的对象,都是独立的个体了,如果p1有其他的关系,那么如何呢,就如同你克隆了一个人,尽管这个克隆人和本体的基本属性相同,但会有相同的记忆吗会有复杂的社会关系吗? 显然并不会
那么假如这个张三这个人有同学这个类,现在如何让克隆体也有这个同学类呢。下面精简一下代码
class People { public $name = '张三'; public $mate; /** * 构造函数中加载同学对象 */ public function __construct() { $this->mate = new Classmate(); } } /** * 同学类 */ class Classmate { public $name ="王五"; } $p1 = new People(); $p2 = clone $p1; $p2 ->name = "ll"; echo $p1->name; echo $p2->name; $p2->mate->name = "ll"; echo $p1->mate->name; 复制代码
然后可以发现p2可以改名字也就是p2的普通属性实现了深拷贝 而mate对象属性中的名字也会改变,存在一定的问题
一般有两种解决方法:
class People { public $name = '张三'; public $mate; /** * 构造函数中加载同学对象 */ public function __construct() { $this->mate = new Classmate(); } //重写clone函数 public function __clone() { $this->mate = clone $this->mate; } } /** * 同学类 */ class Classmate { public $name ="王五"; } $p1 = new People(); $p2 = clone $p1; $p2 ->name = "ll"; echo $p1->name; echo $p2->name; $p2->mate->name = "ll"; echo $p1->mate->name;//输出还是王五 复制代码
这样就可以解决了,但是如果classmate中有很多属性,或者people类要引入很多类,那么这样的重写clone函数就会变得很麻烦
这种方法不用修改函数比较简单
<?php class People { public $name = '张三'; public $mate; /** * 构造函数中加载同学对象 */ public function __construct() { $this->mate = new Classmate(); } } /** * 同学类 */ class Classmate { public $name ="王五"; } $p1 = new People(); $p2 = serialize($p1); $p2 = unserialize($p2); $p2 ->name = "ll"; $p2->mate->name = "ll"; echo $p1->mate->name; 复制代码
还可以用json_encode之后再json_decode,实现赋值和法二一样
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!