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

举报
1_bit 发表于 2021/05/26 18:10:25 2021/05/26
【摘要】 如果错误和不足请给予指出,谢谢~ (⊙_⊙) 在开始使用clone之前我们下先看以下一个小例子: <?php //首先定义一个test一个类 class Testclass { //成员变量是$value1 public $value1; } //随后new一个obj1 $obj1 = new Testclass(); //复制成员变量的值为qqq $ob...

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

(⊙_⊙)

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

<?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);
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

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

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

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

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

<?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);

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

注意看这一段代码:

$obj2 =clone $obj1;
  
 
  • 1

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

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

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

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

<?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);
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

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

//引用value_1的值,注意,是引用
$obj1->value1 = &$vlaue_1;
  
 
  • 1
  • 2

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

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

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

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

<?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"
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

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

文章来源: i1bit.blog.csdn.net,作者:A757291228,版权归原作者所有,如需转载,请联系作者。

原文链接:i1bit.blog.csdn.net/article/details/57457498

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。