PHP对象克隆clone用法示例:浅克隆与深克隆的区别

陈默
陈默
发布时间:2026-10-13| 4人浏览过
原创

PHP 对象克隆使用 clone 关键字,默认行为为浅克隆。若对象包含其他对象属性,浅克隆会导致新旧对象共享同一子对象引用。要实现深克隆(Deep Clone),需在被克隆类中定义 __clone() 魔术方法,在其中对嵌套对象再次执行 clone,从而确保所有层级数据彻底独立。

浅克隆:默认行为与局限性

在 PHP 中,直接使用 clone $obj 进行对象克隆时,系统默认执行的是浅克隆(Shallow Copy)。这意味着:

  • 标量类型(如 int, string, float 等)的值会被完整复制。
  • 对象类型的属性仅仅复制其引用地址,新旧对象的该属性指向同一个对象实例。
  • 资源类型(Resource)通常无法通过 clone 有效隔离,需谨慎处理。

这种机制下,如果修改新对象中的嵌套对象属性,原对象也会随之改变,因为它们共享同一个内部对象。

第1步:准备包含嵌套对象的类结构

首先定义两个类 B 和 A,其中 A 包含一个类型为 B 的属性 $b。

<?php
class B {
    public $val = 10;
}

class A {
    public $val = 20;
    public $b;

    public function __construct() {
        $this->b = new B();
    }
}

第2步:执行浅克隆并验证独立性

创建对象 A 的实例,克隆为新实例,然后分别修改两者的属性,观察 var_dump 输出结果。

<?php
$obj_a = new A();
$obj_b = clone $obj_a; // 浅克隆

// 修改原对象属性
$obj_a->val = 30;
$obj_a->b->val = 40; // 修改嵌套对象

var_dump($obj_a);
echo '<br>';
var_dump($obj_b);

第3步:分析浅克隆运行结果

运行上述代码,输出如下:

object(A)[1]
 public 'val' => int 30
 public 'b' => 
  object(B)[2]
   public 'val' => int 40

object(A)[3]
 public 'val' => int 20
 public 'b' => 
  object(B)[2]
   public 'val' => int 40

关键观察:

  • $obj_a 的 val 变为 30,$obj_b 保持 20,说明标量值已独立复制。
  • 两者内部的 b 属性对应的对象 ID 均为 [2]。这意味着它们指向内存中的同一个 B 对象实例。因此,修改 $obj_a->b->val 后,$obj_b->b->val 也变成了 40。

深克隆:通过 __clone 实现完全独立

当需要确保对象及其所有嵌套子对象都完全独立时,必须实现深克隆。这需要在被克隆的类中定义 __clone() 魔术方法。该方法会在 clone 操作完成后自动触发。

第1步:在类中添加 __clone 方法

在类 A 中添加 __clone 方法,手动对嵌套的对象属性再次执行 clone 操作。

<?php
class B {
    public $val = 10;
}

class A {
    public $val = 20;
    public $b;

    public function __construct() {
        $this->b = new B();
    }

    // 实现深克隆逻辑
    public function __clone() {
        // 对嵌套对象再次克隆,生成新的实例
        $this->b = clone $this->b;
    }
}

第2步:测试深克隆效果

重复之前的测试步骤,创建新实例并修改属性。

<?php
$obj_a = new A();
$obj_b = clone $obj_a; // 触发 __clone 方法

$obj_a->val = 30;
$obj_a->b->val = 40;

var_dump($obj_a);
echo '<br>';
var_dump($obj_b);

第3步:分析深克隆运行结果

运行结果如下:

object(A)[1]
 public 'val' => int 30
 public 'b' => 
  object(B)[2]
   public 'val' => int 40

object(A)[3]
 public 'val' => int 20
 public 'b' => 
  object(B)[4]
   public 'val' => int 10

关键观察:

  • $obj_b 的 val 保持 20,$obj_b->b->val 保持初始值 10。
  • 注意 $obj_b->b 的对象 ID 变为了 [4],而 $obj_a->b 是 [2]。
  • 这表明 $obj_b 拥有了一个全新的 B 对象副本,与 $obj_a 的内部状态完全隔离,互不影响。

总结与注意事项

  • 浅克隆适用场景:当嵌套对象是不可变的,或者业务逻辑允许共享子对象状态时,使用默认的浅克隆更高效简单。
  • 深克隆适用场景:当对象作为配置项、缓存数据或需要严格状态隔离时,必须使用深克隆以避免副作用。
  • 递归复杂度:如果对象结构非常复杂且存在循环引用,简单的递归 __clone 可能不够,需借助工具库或序列化/反序列化方式处理(但需注意资源类型无法序列化)。
  • 性能考量:深克隆涉及多次内存分配和数据复制,对于大型对象树,性能损耗高于浅克隆,应根据实际需求权衡。

以上就是 PHP 对象 clone 浅克隆和深克隆用法的详细内容,更多关于 PHP 面向对象程序设计入门教程的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。