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 相关文章推荐
mysql中存储过程、函数的一些问题
Feb 14 PHP
FCKeditor添加自定义按钮
Mar 27 PHP
php imagecreatetruecolor 创建高清和透明图片代码小结
May 15 PHP
PHP 多维数组的排序问题 根据二维数组中某个项排序
Nov 09 PHP
php 操作数组(合并,拆分,追加,查找,删除等)
Jul 20 PHP
Laravel中使用阿里云OSS Composer包分享
Feb 10 PHP
php实现搜索一维数组元素并删除二维数组对应元素的方法
Jul 06 PHP
四个PHP非常实用的功能
Sep 29 PHP
WordPress中用于更新伪静态规则的PHP代码实例讲解
Dec 18 PHP
PHP编程入门的基本语法知识点总结
Jan 26 PHP
自写的利用PDO对mysql数据库增删改查操作类
Feb 19 PHP
PHP后台实现微信小程序登录
Aug 03 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颜色转换函数hex-rgb(将十六进制格式转成十进制格式)
2013/09/23 PHP
PHP实现获取文件后缀名的几种常用方法
2015/08/08 PHP
浅谈mysql_query()函数的返回值问题
2016/09/05 PHP
php实现的mysqldb读写分离操作类示例
2017/02/07 PHP
通用javascript脚本函数库 方便开发
2009/10/13 Javascript
javascript下arguments,caller,callee,call,apply示例及理解
2009/12/24 Javascript
JQuery 引发两次$(document.ready)事件
2010/01/15 Javascript
js 第二代身份证号码的验证机制代码
2011/05/12 Javascript
jquery学习笔记 用jquery实现无刷新登录
2011/08/08 Javascript
javascript模拟实现C# String.format函数功能代码
2013/11/25 Javascript
文本框水印提示效果的简单实现代码
2014/02/22 Javascript
js触发onchange事件的方法说明
2014/03/08 Javascript
javascript中if和switch,==和===详解
2015/07/30 Javascript
基于jquery实现日历签到功能
2020/09/11 Javascript
bootstrap学习笔记之初识bootstrap
2016/06/21 Javascript
js通过classname来获取元素的方法
2016/11/24 Javascript
老生常谈js-react组件生命周期
2017/05/02 Javascript
js传递数组参数到后台controller的方法
2018/03/29 Javascript
Vue单页应用引用单独的样式文件的两种方式
2018/03/30 Javascript
node.js express框架实现文件上传与下载功能实例详解
2019/10/15 Javascript
vue 翻页组件vue-flip-page效果
2020/02/05 Javascript
ES6扩展运算符和rest运算符用法实例分析
2020/05/23 Javascript
jdk1.8+vue elementui实现多级菜单功能
2020/09/24 Javascript
代码详解django中数据库设置
2019/01/28 Python
Python pandas.DataFrame调整列顺序及修改index名的方法
2019/06/21 Python
Anaconda 查看、创建、管理和使用python环境的方法
2019/12/03 Python
django 多数据库及分库实现方式
2020/04/01 Python
小天鹅官方商城:LittleSwan
2017/06/16 全球购物
一个SQL面试题
2014/08/21 面试题
sealed修饰符是干什么的
2012/10/23 面试题
会计毕业生自我鉴定
2013/11/04 职场文书
工商技校毕业生自荐信
2013/11/15 职场文书
学生顶撞老师的检讨书
2014/09/17 职场文书
vue实现水波涟漪效果的点击反馈指令
2021/05/31 Vue.js
pytorch finetuning 自己的图片进行训练操作
2021/06/05 Python
JavaScript实现队列结构过程
2021/12/06 Javascript