PHP开发过程的那些坑(一) ——对象拷贝

PHP开发过程的那些坑(一)——对象拷贝

(原创内容,转载请注明来源,谢谢)

坑:

做单元测试的过程中,想要运用@dataProvider方式分别传两个不同的对象过去。一开始不清楚对象拷贝存在深拷贝和浅拷贝的事情,直接使用等号进行拷贝,导致结果不是想要的结果,调试了很久以后,发现此问题。

举例:

Class Test{
         public $a;
         public $b;
         public function __construct($a, $b){
         $this->a = $a;
         $this->b = $b;
}
}
$test1 = new Test(1,2);
$test2 = $test1;
$test2->a =2;

此时,$test1和$test2的结果都是2,即$test1的属性$a的值也被改了。不是我想要的结果。

分析:

对象拷贝分为深拷贝和浅拷贝:

深拷贝:赋值时值完全复制,完全的copy,对其中一个作出改变,不会影响另一个。

浅拷贝:赋值时,引用赋值,相当于取了一个别名。对其中一个修改,会影响另一个。使用等号拷贝两个对象,就属于浅拷贝。

改进措施:

1、使用PHP的clone函数

将上述$test2 =$test 1改为$test2 = clone $test1后,再对$test2->a进行复制——$test2->a = 2,则$test1->a的值还是1,没有被改动。

2、举一反三,经过查资料,如果使用clone函数,对象中的普通的属性可以实现深拷贝。但是,如果对象的属性中还有对象,即出现类组合的情况,则对此种情况的属性仍是浅拷贝。为了解决此问题,有三种方案:

2.1 方案一

重写类的魔术方法——克隆函数__clone()

在上述Test类中,加一个属性,如下:

Public $obj;//此属性用于存放类的示例

为了深拷贝$obj,则需在上述Test类中,加一个方法,如下:

         publicfunction __clone(){
                   $this->obj= clone $this->obj;
}

但是,在实际工程中,此方法往往不容易实现,因为经常需要涉及的类是框架公共文件、公共接口、其他人或者其他项目的文件等,不易或者没有条件改动里面的源码。因此,下面两个方案更佳。

2.2 方案二

采用序列化和反序列化。

         classOther{
                   public$x;
                   publicfunction __construct($x){
         $this->x = $x;
}
}
class Test{
         public $a;
         public $b;
         public $obj;
         public function __construct($a, $b,$obj){
         $this->a = $a;
         $this->b = $b;
         $this->obj = newOther(10);
}
}
$test1 = newTest(1,2);
$test2 = serialize($test1);
$test2 =unserialize($test2);

反序列化后,可以对$test进行操作,不会影响到$test1。

如果安装了PHP的igbinary模块,还可以使用igbinary_serialize和igbinary_unserialize的方式进行序列化和反序列化,对于数据量大的情况下,该方法效率更高,处理速度更快。

2.3 方案三

         json_encode和json_decode。

方法和上述类似,可以用此方法将$test1进行转换后赋值给$test2。

——written by linhxx 2017.06.23

原文发布于微信公众号 - 决胜机器学习(phpthinker)

原文发表时间:2017-06-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏智能计算时代

Envoy架构概览(2):HTTP过滤器,HTTP路由,gRPC,WebSocket支持,集群管理器

HTTP过滤器 就像网络级别的过滤堆栈一样,Envoy在连接管理器中支持HTTP级别的过滤堆栈。可以编写过滤器,在不知道底层物理协议(HTTP / 1.1,HT...

2946
来自专栏Java技术栈

让面试官颤抖的 HTTP 2.0 协议面试题

Http协议,对于拥有丰富开发经验的程序员来说简直是信手拈来,家常便饭。虽然天天见,但是对于http协议的问题,可能很多人在没有积极准备的情况下,不一定能很好的...

1042
来自专栏JetpropelledSnake

Python Web学习笔记之并发编程的孤儿进程与僵尸进程

1183
来自专栏步履前行

深入理解JVM--(1)运行时的数据区域划分-程序计数器

  最近在学习jvm,准备在园子里写个系列笔记,有什么问题大家可以一起探讨。今天学习数据区域划分的第一部分--程序计数器。   JVM在运行时会把管理的内存划...

3456
来自专栏Java技术

让面试官颤抖,HTTP2.0协议之你应该要准备的面试题

Http协议,对于拥有丰富开发经验的程序员来说简直是信手拈来,家常便饭。虽然天天见,但是对于http协议的问题,可能很多人在没有积极准备的情况下,不一定能很好的...

643
来自专栏祝威廉

Spark Shuffle Write阶段磁盘文件分析

上篇写了 Spark Shuffle 内存分析 后,有不少人提出了疑问,大家也对如何落文件挺感兴趣的,所以这篇文章会详细介绍,Sort Based Shuff...

461
来自专栏北京马哥教育

运维架构师进阶:Linux进程管理

来源:IBM 译者:ljianhui 链接:blog.csdn.net/ljianhui/article/details/46718835 1.1 Linu...

2759
来自专栏owent

小记最近踩得两个C++坑

记一下最近踩得两个C++独有的暗坑,其中一个和ABI相关。第二个坑其实之前研究过,但是没有实例,这次算是碰到了个典型的实例。

642
来自专栏Golang语言社区

package debug

Package debug contains facilities for programs to debug themselves while they ar...

1125
来自专栏更流畅、简洁的软件开发方式

【开源】QuickPager ASP.NET2.0分页控件 v2.0.0.2版本。

下载地址:http://files.cnblogs.com/jyk/Page2.0.0.2_080701.rar 这回只有 dll文件。请把包里的文件拷贝到...

1886

扫描关注云+社区