💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
### **clone关键字** **用于克隆一个完全一样的对象,克隆之后两个对象互不干扰。** > 适用场景:在编码过程中,有一个对象A,在某一时刻A中已经包含了一些有效值,此时可能会需要一个和A完全相同新对象B,并且此后对B任何改动都不会影响到A中的值,也就是说,A与B是两个独立的对象,但B的初始值是由A对象确定的。 ``` // 使用clone关键字之前的复制效果实例 // // 定义一个类,类中定义一个公共成员变量 class TestClass { public $value; } $obj = new TestClass(); // 实例化TestClass类的对象 $obj->value = 'qq'; // 给成员变量赋值 var_dump($obj); // object(TestClass)#228 (1) { ["value"]=> string(2) "qq" } $obj2 = $obj; // 将$obj赋值给$obj2变量,等同于复制一个$obj $obj2->value = 'zz'; // 更改$value的值 var_dump($obj); // object(TestClass)#228 (1) { ["value"]=> string(2) "zz" } var_dump($obj2); // object(TestClass)#228 (1) { ["value"]=> string(2) "zz" } ``` 从以上的例子可以看出来当实例化对象赋值给其他变量时,改变实例化对象和改变赋值对象,另一方都会随之改变。这是因为普象的赋值,仅仅是把新对象指向对象存储的地址(即 $obj给了$obj2它的地址,就和引用一样,$obj2指向了$obj,所以导致两者所执行的操作将会收到影响)。 ``` // 使用clone关键字之后的复制效果实例 // // 定义一个类,类中定义一个公共成员变量 class TestClass { public $value; } $obj = new TestClass(); // 实例化TestClass类的对象 $obj->value = 'qq'; // 给成员变量赋值 var_dump($obj); // object(TestClass)#228 (1) { ["value"]=> string(2) "qq" } $obj2 = clone $obj; // 使用clone关键字克隆$obj $obj2->value = 'zz'; // 更改$value的值 var_dump($obj); // object(TestClass)#228 (1) { ["value"]=> string(2) "qq" } var_dump($obj2); // object(TestClass)#228 (1) { ["value"]=> string(2) "zz" } ``` 可以看出,使用clone关键字之后,更改$obj2的成员变量值并不会对$obj的成员变量产生影响,克隆之后的两个对象$obj和$obj2是互不影响,互相独立的。 ### **__clone方法** **用于重写原本的属性和方法;__clone() 方法只会在对象被克隆的时候自动调用。** > __clone()方法对一个对象实例进行的浅复制,对象内的基本数值类型进行的是传值复制,而对象内的对象型成员变量,如果不重写__clone方法,显式的clone这个对象成员变量的话,这个成员变量就是传引用复制,而不是生成一个新的对象。 ``` // 定义age类 class Age { public $balance; public function __construct($balance) { $this->balance = $balance; } } // // 定义第二个类,类中包括两个公共成员以及构造函数、克隆方法 class IndexService { public $age; // 对象属性成员变量 public $name; // 非对象属性成员变量 public function __construct($name, Age $age) { $this->name = $name; $this->age = $age; } // 使用clone的时候触发 public function __clone() { $this->name = 'name:'.$this->name; $this->age = clone $this->age; // 这个对象会被强制复制,这样就不会指向原来的对象。 } } // 运行 $obj = new IndexService('peter',new Age(20)); $obj2 = clone $obj; $obj2->age->balance = 10; var_dump($obj); var_dump($obj2); // age对象中的balance值更改为10,name值也被更改。 ``` ![](https://img.kancloud.cn/02/dc/02dcaea6a562a59a69e4a01b3e9a638f_511x254.png) > 注意: __clone()方法中的clone操作只能用于对象,如果用于非对象属性,将会报错:# 致命错误: __clone method called on non-object。 > 例子中的age就是一个对象。 以上例子中,$age对象被强制复制,不会指向原来的对象,所以修改其中的值之后,并不会对原来对象有影响;如果不加上`$this->age = clone $this->age;`这行代码,运行结果则变成这样:两个对象的age对象的balance值都改成了10。 ![](https://img.kancloud.cn/90/70/90707a423336d80e3f668733f7cbe758_526x251.png)