ZetCode

PHP 克隆关键字

最后修改于 2025 年 4 月 16 日

PHP clone 关键字创建对象的副本。与简单赋值不同,克隆会创建一个具有复制属性值的新对象。这对于在 PHP 中使用对象引用至关重要。

基本定义

clone 关键字对对象执行浅拷贝。它创建一个具有相同属性值的新对象实例。对象中的引用在克隆中仍然是引用。

PHP 在克隆完成后调用 __clone 魔术方法。您可以覆盖此方法以自定义克隆行为。这允许深拷贝或其他克隆后操作。

语法:$clone = clone $object;。克隆运算符创建一个具有相同类和属性的新对象。原始对象和克隆对象在内存中是不同的对象。

基本对象克隆

此示例演示了克隆关键字的最简单用法。

basic_clone.php
<?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 对象并克隆它。更改克隆的属性不会影响原始对象。两个对象在内存中独立存在。这显示了基本的克隆行为。

浅拷贝行为

此示例演示了克隆如何对对象属性执行浅拷贝。

shallow_copy.php
<?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() 创建深拷贝。

deep_clone.php
<?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 对象。这将创建一个真正的深拷贝,其中所有对象都被复制。现在对克隆作者的更改不会影响原始对象。

使用私有属性克隆

此示例演示了如何使用私有属性克隆对象。

private_properties.php
<?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

克隆复制私有属性,就像公共属性一样。克隆对象获得其自己的所有属性副本。访问修饰符不影响克隆行为。克隆是原始对象的完整副本。

使用继承进行克隆

此示例展示了克隆如何与继承类一起工作。

inheritance_clone.php
<?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() 方法都会被调用。如果需要,应显式调用父类方法。来自两个类的所有属性都被复制。输出显示两个克隆方法正在执行。

使用魔术方法克隆

此示例演示了克隆与其他魔术方法交互的对象。

magic_methods.php
<?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() 方法可以在克隆期间修改属性。静态属性在所有实例之间共享。计数跟踪原始对象和克隆对象。

使用复杂对象进行克隆

此示例演示了如何克隆具有多个嵌套对象的对象。

complex_clone.php
<?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 实例。此模式对于复杂对象图很常见。

最佳实践

来源

PHP 对象克隆文档

本教程涵盖了 PHP 对象克隆,并提供了实际示例,展示了克隆关键字在各种场景中的用法。了解克隆对于在 PHP 中进行适当的面向对象编程至关重要。

作者

我叫 Jan Bodnar,是一位热情的程序员,拥有丰富的编程经验。自 2007 年以来,我一直在撰写编程文章。迄今为止,我撰写了 1,400 多篇文章和 8 本电子书。我拥有超过十年的编程教学经验。

列出 所有 PHP 教程