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 相关文章推荐
php4的session功能评述(三)
Oct 09 PHP
一个更简单的无限级分类菜单代码
Jan 16 PHP
纯真IP数据库的应用 IP地址转化成十进制
Jun 14 PHP
mysql总结之explain
Feb 27 PHP
PHP在线生成二维码(google api)的实现代码详解
Jun 04 PHP
php 字符串中的\n换行符无效、不能换行的解决方法
Apr 02 PHP
PHP生成迅雷、快车、旋风等软件的下载链接代码实例
May 12 PHP
php去掉URL网址中带有PHPSESSID的配置方法
Jul 08 PHP
php操作xml入门之xml基本介绍及xml标签元素
Jan 23 PHP
PHP快速推送微信模板消息
Apr 14 PHP
PHP chunk_split()函数讲解
Feb 12 PHP
laravel-admin自动生成模块,及相关基础配置方法
Oct 08 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
php实现批量压缩图片文件大小的脚本
2014/07/04 PHP
PHP使用PDO操作数据库的乱码问题解决方法
2016/04/08 PHP
PHP编程 SSO详细介绍及简单实例
2017/01/13 PHP
用js怎么把&字符换成"&amp:"
2006/10/19 Javascript
js检测客户端不是firefox则提示下载
2007/04/07 Javascript
js跟随滚动条滚动浮动代码
2009/12/31 Javascript
主页面中的两个iframe实现鼠标拖动改变其大小
2013/04/16 Javascript
nodejs中实现sleep功能实例
2015/03/24 NodeJs
js简单实现点击左右运动的方法
2015/04/10 Javascript
JS访问SWF的函数用法实例
2015/07/01 Javascript
jQuery左侧大图右侧小图焦点图幻灯切换代码分享
2015/08/19 Javascript
基于JavaScript怎么实现让歌词滚动播放
2015/11/03 Javascript
跟我学习javascript的prototype原型和原型链
2015/11/18 Javascript
JavaScript实现的select点菜功能示例
2017/01/16 Javascript
Angular.JS去掉访问路径URL中的#号详解
2017/03/30 Javascript
详解使用Node.js 将txt文件转为Excel文件
2017/07/05 Javascript
利用纯JS实现像素逐渐显示的方法示例
2017/08/14 Javascript
vue动态删除从数据库倒入列表的某一条方法
2018/09/29 Javascript
JavaScript JSON数据处理全集(小结)
2019/08/15 Javascript
使用layer弹窗,制作编辑User信息页面的方法
2019/09/27 Javascript
在vue+element ui框架里实现lodash的debounce防抖
2019/11/13 Javascript
视觉直观感受若干常用排序算法
2017/04/13 Python
Python 调用Java实例详解
2017/06/02 Python
python爬虫headers设置后无效的解决方法
2017/10/21 Python
python中 logging的使用详解
2017/10/25 Python
numpy使用技巧之数组过滤实例代码
2018/02/03 Python
python 运用Django 开发后台接口的实例
2018/12/11 Python
Python的in,is和id函数代码实例
2020/04/18 Python
Python使用文件操作实现一个XX信息管理系统的示例
2020/07/02 Python
Pygame框架实现飞机大战
2020/08/07 Python
CSS3的新特性介绍
2008/10/31 HTML / CSS
HTML5 实现图片上传预处理功能
2020/02/06 HTML / CSS
倩碧美国官网:Clinique美国
2016/07/20 全球购物
《燕子专列》教学反思
2014/02/21 职场文书
设备管理实施方案
2014/05/31 职场文书
MySQL数字类型自增的坑
2021/05/07 MySQL