前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >php之clone 复制对象以及__clone魔术方法

php之clone 复制对象以及__clone魔术方法

作者头像
1_bit
发布2021-01-14 16:56:49
8700
发布2021-01-14 16:56:49
举报
文章被收录于专栏:我的知识小屋我的知识小屋

如果错误和不足请给予指出,谢谢~

(⊙_⊙)

在开始使用clone之前我们下先看以下一个小例子:

代码语言:javascript
复制
<?php 
//首先定义一个test一个类
class Testclass {
    //成员变量是$value1
    public $value1;
}
//随后new一个obj1
$obj1 = new Testclass();
//复制成员变量的值为qqq
$obj1->value1 = "qqq";
//我们使用赋值符号给左边obj2赋值obj1
$obj2 = $obj1;
//我们在这里把obj2的的value1复制为eee
$obj2->value1 ="eee";     
//随后我们打印出两者的值
var_dump($obj1);
echo '<br/>';
var_dump($obj2);

为了查看方便,我把那个解释写在了注释=。=。(这句话总感觉怪怪的)

我们运行一下,发现如下结果:

运行结果
运行结果

是不是两者的值都是一样的? 那是因为(借用php手册的话就是):当对象被复制后,PHP 5 会对对象的所有属性执行一个浅复制(shallow copy)。所有的引用属性 仍然会是一个指向原来的变量的引用。

其实在这里就是obj1给了obj2它的地址,就和引用一样,obj2指向了obj1,所以导致两者所执行的操作将会收到影响。那么该如何解决这样情况呢?当然是使用clone了;列如下代码:

代码语言:javascript
复制
<?php 
//首先定义一个test一个类
class Testclass {
    //成员变量是$value1
    public $value1;
}
//随后new一个obj1
$obj1 = new Testclass();
//复制成员变量的值为qqq
$obj1->value1 = "qqq";
//在这里我们使用clone来赋值obj1
$obj2 =clone $obj1;
//我们在这里把obj2的的value1复制为eee
$obj2->value1 ="eee";     
//随后我们打印出两者的值
var_dump($obj1);
echo '<br/>';
var_dump($obj2);

注意看这一段代码:

代码语言:javascript
复制
$obj2 =clone $obj1;

在这里使用了clone,这样就会没事了,看如下运行结果:

运行结果
运行结果

是否发现两者并没有相互影响呢?

好了,在这里已经完成了基本的clone的讲解了,现在我们来深入一下(抽根烟压压惊。。。 ( ´´ิ∀´ิ` ) )

我们接下来看看一个例子:

代码语言:javascript
复制
<?php 
//首先定义一个test一个类
class Testclass {
    //成员变量是$value1
    public $value1;
}
//在这里是定义了一个变量
$vlaue_1='bbj';
//随后new一个obj1
$obj1 = new Testclass();
//引用value_1的值,注意,是引用
$obj1->value1 = &$vlaue_1;
//在这里我们使用clone来赋值obj1
$obj2 =clone $obj1;
//我们在这里把obj2的的value1复制为eee
$obj2->value1 ="eee";     
//随后我们打印出两者的值
var_dump($obj1);
echo '<br/>';
var_dump($obj2);

我们的代码和之前的差不多,我们主要看这一行:

代码语言:javascript
复制
//引用value_1的值,注意,是引用
$obj1->value1 = &$vlaue_1;

注意在此是引用哟。 我们看下运行结果:

运行结果
运行结果

是否发现我在obj2改变了value1值之后obj1的值也会改变?因为在这里obj1赋值成员变量的时候使用了&取址。将会成为一个引用的状态。那么我们如果想要把这个值不守clone出来的对象的值影响该怎么办呢?

那么在这里我们只需要在此clone一下这个成员变量就好了,该如何clone了?那么我们现在就可以使用我们的魔法方法__clone了。

首先我们来说说__clone()在什么状态下触发:

当我们有clone操作的时候将会除非这个类里面的__clone方法。那么把我们的成员变量在__clone方法里面clone一下就好了,如下代码演示: 注:clone只能用于对象克隆,对象复制。记住,如果你clone一个非对象变量将会报错no obj。。。 以下例子是我从网上找的一个例子,感觉不错,这里将用这个例子来讲解魔法方法__clone的使用: 本来这个是没有注释的,我顺便把解释丢到了里面,这样强制clone后就不会指向原来的对象了。

代码语言:javascript
复制
<?php 
class testClass
{
 public $str_data;//这里是一个非对象类型
 public $obj_data;//在这里这是一个对象,可以看下面将会给一个对象给他
//使用clone的时候触发
 public function __clone() {
   $this->obj_data = clone $this->obj_data;//这个对象将会被克隆,会被强制复制,这样就不会指向原来的对象了
 }
}
//new一个datatime对给datatimeobj
$dateTimeObj = new DateTime("2014-07-05", new DateTimeZone("UTC"));

$obj1 = new testClass();//new一个testclass
$obj1->str_data ="aaa"; //复制aaa
$obj1->obj_data = $dateTimeObj; //给obj_data一个对象datetimeobj

$obj2 = clone $obj1; //克隆obj1给obj2
var_dump($obj1);  // str_data:"aaa"  obj_data:"2014-07-05 00:00:00"
var_dump($obj2);  // str_data:"aaa"  obj_data:"2014-07-05 00:00:00"
$obj2->str_data ="bbb"; //obj2给一个值bbb给strdata
$obj2->obj_data->add(new DateInterval('P10D'));//objdata改变objdata的值

var_dump($obj1);  // str_data:"aaa"  obj_data:"2014-07-05 00:00:00"
var_dump($obj2);  // str_data:"aaa"  obj_data:"2014-07-15 00:00:00"
var_dump($dateTimeObj);  //"2014-07-05 00:00:00"

以上就是clone的使用方法了=。=。。。 如果错误请给予指出,谢谢~

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-02-26 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档