UNPKG

manual-php

Version:
278 lines (235 loc) 6.87 kB
# 对象复制 在多数情况下,我们并不需要完全复制一个对象来获得其中属性。但有一个情况下确实需要:如果第一个对象中保存着第二个对象的引用,当你复制第一个对象时,你想使用的对象不再是第二个对象而是它的一个副本,那么你必须得到第二个对象的一个副本。对象复制可以通过 `clone` 关键字来完成(如果可能,这将调用对象的 `__clone()` 方法)。对象中的 `__clone()` 方法不能被直接调用。当对象被复制后, PHP 会对对象的所有属性执行一个浅复制。所有的引用属性仍然会是一个指向原来的变量的引用。 ```php <?php class Cat { /** * The name of cat. * * @var string */ public string $name; /** * The age of cat. * * @var int */ public int $age; /** * Store the name and age. * * @param string $name * @param int $age * @return void */ public function __construct(string $name, int $age) { $this->name = $name; $this->age = $age; } } class Dog { /** * The name of dog. * * @var string */ public string $name; /** * Store an instance of cat. * * @var Cat */ public Cat $cat; } $spike = new Dog(); $spike->name = 'Spike'; $spike->cat = new Cat('Tom', 6); $tyke = clone $spike; var_dump($spike); // object(Dog)#1 (2) { ["name"]=> string(5) "Spike" ["cat"]=> object(Cat)#2 (2) { ["name"]=> string(3) "Tom" ["age"]=> int(6) } } var_dump($tyke); // object(Dog)#3 (2) { ["name"]=> string(5) "Spike" ["cat"]=> object(Cat)#2 (2) { ["name"]=> string(3) "Tom" ["age"]=> int(6) } } $tyke->name = 'Tyke'; $tyke->cat->age = 2; var_dump($spike); // object(Dog)#1 (2) { ["name"]=> string(5) "Spike" ["cat"]=> object(Cat)#2 (2) { ["name"]=> string(3) "Tom" ["age"]=> int(2) } } var_dump($tyke); // object(Dog)#3 (2) { ["name"]=> string(4) "Tyke" ["cat"]=> object(Cat)#2 (2) { ["name"]=> string(3) "Tom" ["age"]=> int(2) } } ``` 当复制完成时,如果定义了 `__clone()` 方法,则新创建的对象(复制生成的对象)中的 `__clone()` 方法会被调用,可用于修改属性的值(如果有必要的话)。 ```php <?php class Cat { /** * The name of cat. * * @var string */ public string $name; /** * The age of cat. * * @var int */ public int $age; /** * Store the name and age. * * @param string $name * @param int $age * @return void */ public function __construct(string $name, int $age) { $this->name = $name; $this->age = $age; } } class Dog { /** * The name of dog. * * @var string */ public string $name; /** * Store an instance of cat. * * @var Cat */ public Cat $cat; /** * Complete deep copy. * * @param void * @return void */ public function __clone() { $this->cat = clone $this->cat; } } $spike = new Dog(); $spike->name = 'Spike'; $spike->cat = new Cat('Tom', 6); $tyke = clone $spike; var_dump($spike); // object(Dog)#1 (2) { ["name"]=> string(5) "Spike" ["cat"]=> object(Cat)#2 (2) { ["name"]=> string(3) "Tom" ["age"]=> int(6) } } var_dump($tyke); // object(Dog)#3 (2) { ["name"]=> string(5) "Spike" ["cat"]=> object(Cat)#4 (2) { ["name"]=> string(3) "Tom" ["age"]=> int(6) } } $tyke->name = 'Tyke'; $tyke->cat->age = 2; var_dump($spike); // object(Dog)#1 (2) { ["name"]=> string(5) "Spike" ["cat"]=> object(Cat)#2 (2) { ["name"]=> string(3) "Tom" ["age"]=> int(6) } } var_dump($tyke); // object(Dog)#3 (2) { ["name"]=> string(4) "Tyke" ["cat"]=> object(Cat)#4 (2) { ["name"]=> string(3) "Tom" ["age"]=> int(2) } } ``` 可以将对象序列化后再反序列化来完成对象的深复制。 ```php <?php class Cat { /** * The name of cat. * * @var string */ public string $name; /** * The age of cat. * * @var int */ public int $age; /** * Store the name and age. * * @param string $name * @param int $age * @return void */ public function __construct(string $name, int $age) { $this->name = $name; $this->age = $age; } } class Dog { /** * The name of dog. * * @var string */ public string $name; /** * Store an instance of cat. * * @var Cat */ public Cat $cat; } $spike = new Dog(); $spike->name = 'Spike'; $spike->cat = new Cat('Tom', 6); $tyke = unserialize(serialize($spike)); var_dump($spike); // object(Dog)#1 (2) { ["name"]=> string(5) "Spike" ["cat"]=> object(Cat)#2 (2) { ["name"]=> string(3) "Tom" ["age"]=> int(6) } } var_dump($tyke); // object(Dog)#3 (2) { ["name"]=> string(5) "Spike" ["cat"]=> object(Cat)#4 (2) { ["name"]=> string(3) "Tom" ["age"]=> int(6) } } $tyke->name = 'Tyke'; $tyke->cat->age = 2; var_dump($spike); // object(Dog)#1 (2) { ["name"]=> string(5) "Spike" ["cat"]=> object(Cat)#2 (2) { ["name"]=> string(3) "Tom" ["age"]=> int(6) } } var_dump($tyke); // object(Dog)#3 (2) { ["name"]=> string(4) "Tyke" ["cat"]=> object(Cat)#4 (2) { ["name"]=> string(3) "Tom" ["age"]=> int(2) } } ``` 还可以将对象进行 `JSON` 编码后再解码来完成对象的深复制。 ```php <?php class Cat { /** * The name of cat. * * @var string */ public string $name; /** * The age of cat. * * @var int */ public int $age; /** * Store the name and age. * * @param string $name * @param int $age * @return void */ public function __construct(string $name, int $age) { $this->name = $name; $this->age = $age; } } class Dog { /** * The name of dog. * * @var string */ public string $name; /** * Store an instance of cat. * * @var Cat */ public Cat $cat; } $spike = new Dog(); $spike->name = 'Spike'; $spike->cat = new Cat('Tom', 6); $tyke = json_decode(json_encode($spike)); var_dump($spike); // object(Dog)#1 (2) { ["name"]=> string(5) "Spike" ["cat"]=> object(Cat)#2 (2) { ["name"]=> string(3) "Tom" ["age"]=> int(6) } } var_dump($tyke); // object(stdClass)#3 (2) { ["name"]=> string(5) "Spike" ["cat"]=> object(stdClass)#4 (2) { ["name"]=> string(3) "Tom" ["age"]=> int(6) } } $tyke->name = 'Tyke'; $tyke->cat->age = 2; var_dump($spike); // object(Dog)#1 (2) { ["name"]=> string(5) "Spike" ["cat"]=> object(Cat)#2 (2) { ["name"]=> string(3) "Tom" ["age"]=> int(6) } } var_dump($tyke); // object(stdClass)#3 (2) { ["name"]=> string(4) "Tyke" ["cat"]=> object(stdClass)#4 (2) { ["name"]=> string(3) "Tom" ["age"]=> int(2) } } ```