PHP 克隆关键字
最后修改于 2025 年 4 月 16 日
PHP clone 关键字创建对象的副本。与简单赋值不同,克隆会创建一个具有复制属性值的新对象。这对于在 PHP 中使用对象引用至关重要。
基本定义
clone 关键字对对象执行浅拷贝。它创建一个具有相同属性值的新对象实例。对象中的引用在克隆中仍然是引用。
PHP 在克隆完成后调用 __clone 魔术方法。您可以覆盖此方法以自定义克隆行为。这允许深拷贝或其他克隆后操作。
语法:$clone = clone $object;。克隆运算符创建一个具有相同类和属性的新对象。原始对象和克隆对象在内存中是不同的对象。
基本对象克隆
此示例演示了克隆关键字的最简单用法。
<?php
class Book {
public $title;
public function __construct($title) {
$this->title = $title;
}
}
$book1 = new Book("PHP Essentials");
$book2 = clone $book1;
$book2->title = "Advanced PHP";
echo $book1->title; // Outputs: PHP Essentials
echo $book2->title; // Outputs: Advanced PHP
代码创建一个 Book 对象并克隆它。更改克隆的属性不会影响原始对象。两个对象在内存中独立存在。这显示了基本的克隆行为。
浅拷贝行为
此示例演示了克隆如何对对象属性执行浅拷贝。
<?php
class Author {
public $name;
}
class Book {
public $title;
public $author;
public function __construct($title, $authorName) {
$this->title = $title;
$this->author = new Author();
$this->author->name = $authorName;
}
}
$book1 = new Book("PHP Guide", "John Doe");
$book2 = clone $book1;
$book2->author->name = "Jane Smith";
echo $book1->author->name; // Outputs: Jane Smith
克隆复制了作者引用,而不是 Author 对象本身。两本书共享同一个 Author 实例。这是默认的浅拷贝行为。对引用的对象所做的更改会影响两个副本。
实现 __clone()
此示例展示了如何使用 __clone() 创建深拷贝。
<?php
class Author {
public $name;
}
class Book {
public $title;
public $author;
public function __construct($title, $authorName) {
$this->title = $title;
$this->author = new Author();
$this->author->name = $authorName;
}
public function __clone() {
$this->author = clone $this->author;
}
}
$book1 = new Book("PHP Patterns", "Mike Brown");
$book2 = clone $book1;
$book2->author->name = "Sarah Johnson";
echo $book1->author->name; // Outputs: Mike Brown
echo $book2->author->name; // Outputs: Sarah Johnson
当 Book 被克隆时,__clone() 方法克隆 Author 对象。这将创建一个真正的深拷贝,其中所有对象都被复制。现在对克隆作者的更改不会影响原始对象。
使用私有属性克隆
此示例演示了如何使用私有属性克隆对象。
<?php
class User {
private $username;
private $password;
public function __construct($username, $password) {
$this->username = $username;
$this->password = $password;
}
public function getUsername() {
return $this->username;
}
public function setUsername($username) {
$this->username = $username;
}
}
$user1 = new User("admin", "secret123");
$user2 = clone $user1;
$user2->setUsername("editor");
echo $user1->getUsername(); // Outputs: admin
echo $user2->getUsername(); // Outputs: editor
克隆复制私有属性,就像公共属性一样。克隆对象获得其自己的所有属性副本。访问修饰符不影响克隆行为。克隆是原始对象的完整副本。
使用继承进行克隆
此示例展示了克隆如何与继承类一起工作。
<?php
class Animal {
protected $name;
public function __construct($name) {
$this->name = $name;
}
public function __clone() {
echo "Cloning Animal\n";
}
}
class Dog extends Animal {
private $breed;
public function __construct($name, $breed) {
parent::__construct($name);
$this->breed = $breed;
}
public function __clone() {
parent::__clone();
echo "Cloning Dog\n";
}
}
$dog1 = new Dog("Max", "Labrador");
$dog2 = clone $dog1;
当克隆子类时,父类和子类的 __clone() 方法都会被调用。如果需要,应显式调用父类方法。来自两个类的所有属性都被复制。输出显示两个克隆方法正在执行。
使用魔术方法克隆
此示例演示了克隆与其他魔术方法交互的对象。
<?php
class Product {
private $name;
private static $count = 0;
public function __construct($name) {
$this->name = $name;
self::$count++;
}
public function __clone() {
$this->name = "Clone of " . $this->name;
self::$count++;
}
public static function getCount() {
return self::$count;
}
}
$p1 = new Product("Laptop");
$p2 = clone $p1;
echo Product::getCount(); // Outputs: 2
echo $p2->getName(); // Outputs: Clone of Laptop
该示例显示了克隆与静态属性和其他方法的交互。__clone() 方法可以在克隆期间修改属性。静态属性在所有实例之间共享。计数跟踪原始对象和克隆对象。
使用复杂对象进行克隆
此示例演示了如何克隆具有多个嵌套对象的对象。
<?php
class Address {
public $street;
public $city;
}
class Person {
public $name;
public $address;
public function __construct($name, $street, $city) {
$this->name = $name;
$this->address = new Address();
$this->address->street = $street;
$this->address->city = $city;
}
public function __clone() {
$this->address = clone $this->address;
}
}
$person1 = new Person("Alice", "123 Main St", "Springfield");
$person2 = clone $person1;
$person2->name = "Bob";
$person2->address->street = "456 Oak Ave";
echo $person1->address->street; // Outputs: 123 Main St
echo $person2->address->street; // Outputs: 456 Oak Ave
Person 类包含一个 Address 对象。__clone() 方法确保 Address 的深拷贝。如果没有它,两个 Person 将共享同一个 Address 实例。此模式对于复杂对象图很常见。
最佳实践
- 深拷贝:为具有引用的对象实现 __clone()。
- 性能:注意克隆大型对象图。
- 不可变对象:考虑使对象不可变。
- 文档:在您的类中记录克隆行为。
- 测试:彻底测试克隆对象以确保行为正确。
来源
本教程涵盖了 PHP 对象克隆,并提供了实际示例,展示了克隆关键字在各种场景中的用法。了解克隆对于在 PHP 中进行适当的面向对象编程至关重要。
作者
列出 所有 PHP 教程。