PHP中的浅复制与深复制的实例详解


Posted in PHP onOctober 26, 2017

PHP中的浅复制与深复制的实例详解

前言:

最近温习了一下Design Pattern方面的知识,在看到Prototype Pattern这一设计模式时,注意到其中涉及到一个浅复制与深复制的问题。这里来总结一下,提醒自己以后一定要多加注意。

自PHP5起,new运算符自动返回一个引用,一个 对象变量 已经不再保存整个对象的值,只是保存一个标识符来访问真正的对象内容。当对象作为参数传递,作为结果返回,或者赋值给另外一个变量,另外一个变量跟原来的不是引用的关系,只是他们都保存着同一个标识符的拷贝,这个标识符指向同一个对象的真正内容。

这里举个栗子:

class Example1
{
  public $name;

  public function __construct($name)
  {
    $this->name = $name;
  }
}

$ex1 = new Example('test1');// $ex1->name现在是:test1
$ex2 = $ex1;// $ex2->name现在是:test1

$ex2->name = 'test2';// 这样修改一下之后,$ex1->name与$ex2->name都变为了:test2

通过上面这个例子,应该可以理解对象间引用的概念了,那么我们继续往下走,在php中提供了 clone 这个关键字来进行对象复制,还是用上面的类来演示一下:

$ex1 = new Example('test1');// $ex1->name现在是:test1
$ex2 = clone $ex1;//$ex2->name现在是:test1

$ex2->name = 'test2';//现在$ex1->name还是test1,而$ex2->name是test2

这里看到,通过clone之后,$ex1与$ex2是两个不同的对象,他们拥有各自的变量环境。但是这里需要注意,在这两个对象内部,拥有的是值类型的数据,如果是内部拥有的是引用类型,那么通过clone得到的新对象中的引用则仍然指向原引用。这里就引申出 浅复制 与 深复制 的概念:

浅复制: 使用clone来复制对象,这种复制叫做“浅复制“,被赋值对象的所有变量都还有与原来对象相同的值,而所有的对其他对象的引用都仍然指向原来的对象。

深复制:被复制的对象的所有的变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。

默认使用 clone 是进行一个浅复制,那么如何才能进行深复制呢?

方式一:利用__clone方法

public function __clone()
{
  $this->obj = new Obj();
}

这种方式非常直观,但是却有一个很麻烦的操作方式,就是当类中包含多个引用时,你就需要在__clone方法中逐个重新设置。而且还要处理一些循环引用的问题。是很复杂的。

方式二:利用串行化(冷藏与解冻)

$tmp = serialize($ex1);
$ex2 = unserialize($tmp);

这时候得到的$ex2就是一个全新的对象,这个过程在java中也叫作”冷藏“与”解冻“过程。

序列化是一个递归的过程,我们不需要理会被对象内部引用了多少个对象以及引用了多少层对象,我们都可以彻底的复制。方式二真的很黄很暴力,但是我很喜欢。

如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

PHP 相关文章推荐
在命令行下运行PHP脚本[带参数]的方法
Jan 22 PHP
克隆一个新项目的快捷方式
Apr 10 PHP
php htmlspecialchars()与shtmlspecialchars()函数的深入分析
Jun 05 PHP
PHP采集类Snoopy抓取图片实例
Jun 19 PHP
php通过记录IP来防止表单重复提交方法分析
Dec 16 PHP
php调用淘宝开放API实现根据卖家昵称获取卖家店铺ID的方法
Jul 29 PHP
深入剖析浏览器退出之后php还会继续执行么
May 17 PHP
php无限级分类实现方法分析
Oct 19 PHP
PHP生成word文档的三种实现方式
Nov 14 PHP
php使用crypt()函数进行加密
Jun 08 PHP
PHPTree――php快速生成无限级分类
Mar 30 PHP
PHP封装cURL工具类与应用示例
Jul 01 PHP
thinkPHP5实现数据库添加内容的方法
Oct 25 #PHP
thinkPHP5分页功能实现方法分析
Oct 25 #PHP
thinkPHP框架中执行原生SQL语句的方法
Oct 25 #PHP
php调用云片网接口发送短信的实现方法
Oct 25 #PHP
OAuth认证协议中的HMACSHA1加密算法(实例)
Oct 25 #PHP
Laravel学习教程之request validation的编写
Oct 25 #PHP
Yii2框架实现登录、退出及自动登录功能的方法详解
Oct 24 #PHP
You might like
博士208HAF收音机实习报告
2021/03/02 无线电
谈谈PHP语法(5)
2006/10/09 PHP
PHP学习笔记之二
2011/01/17 PHP
Smarty foreach控制循环次数的实现详解
2013/07/03 PHP
php递归遍历多维数组的方法
2015/04/18 PHP
Yii框架实现记录日志到自定义文件的方法
2017/05/23 PHP
Laravel5.5 视图 - 创建视图和数据传递示例
2019/10/21 PHP
JavaScript使用cookie
2007/02/02 Javascript
用javascript实现页面打印的三种方法
2007/03/05 Javascript
JSON JQUERY模板实现说明
2010/07/03 Javascript
jquery.pagination.js 无刷新分页实现步骤分享
2012/05/23 Javascript
js解析xml字符串和xml文档实现原理及代码(针对ie与火狐)
2013/02/02 Javascript
jQuery实现Twitter的自动文字补齐特效
2014/11/28 Javascript
JS代码实现根据时间变换页面背景效果
2016/06/16 Javascript
js简单正则验证汉字英文及下划线的方法
2016/11/28 Javascript
React Native仿美团下拉菜单的实例代码
2017/08/08 Javascript
12条写出高质量JS代码的方法
2018/01/07 Javascript
AngularJS基于http请求实现下载php生成的excel文件功能示例
2018/01/23 Javascript
浅谈Vue SSR中的Bundle的具有使用
2019/11/21 Javascript
Vue实现简单的拖拽效果
2020/08/25 Javascript
vue 自定指令生成uuid滚动监听达到tab表格吸顶效果的代码
2020/09/16 Javascript
vue添加自定义右键菜单的完整实例
2020/12/08 Vue.js
JavaScript 获取滚动条位置并将页面滑动到锚点
2021/02/08 Javascript
[49:08]Secret vs VP 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/20 DOTA
通过mod_python配置运行在Apache上的Django框架
2015/07/22 Python
Python的dict字典结构操作方法学习笔记
2016/05/07 Python
解决pycharm无法识别本地site-packages的问题
2018/10/13 Python
对python 自定义协议的方法详解
2019/02/13 Python
基于python计算滚动方差(标准差)talib和pd.rolling函数差异详解
2020/06/08 Python
用python进行视频剪辑
2020/11/02 Python
介绍一下linux的文件权限
2014/07/20 面试题
端午节粽子促销活动方案
2014/02/02 职场文书
2015年国税春训心得体会
2015/03/09 职场文书
幼儿园校车安全责任书
2015/05/08 职场文书
解决SpringCloud Feign传对象参数调用失败的问题
2021/06/23 Java/Android
Win11 Beta 预览版 22621.575 和 22622.575更新补丁KB5016694发布(附更新内容大全)
2022/08/14 数码科技