美文网首页小白学编程
PHP中的对象复制

PHP中的对象复制

作者: 正义的程序员 | 来源:发表于2018-12-20 22:35 被阅读0次

PHP中,=的作用都是将一个值复制给另一个(大多数编程语言都是一样),将=作用在基本数据类型上时,就直接进行了赋值,并且变量的修改互不影响,如下:

$a = 1;
$b = $a;
$b = 2;
print_r($a);  // 1
print_r($b);  // 2

而在复制对象时,=只是简单地将两个变量指向同一个类实例,测试一下:

class Student
{
    public $name;
    public $age;

    function __construct($name, $age) {
        $this->name = $name;
        $this->age = $age;
    }
}

$student1 = new Student('mike', 19);
$student2 = $student1;

print_r($student1);
print_r($student2);
var_dump($student1 == $student2);
var_dump($student1 === $student2);

// 输出
Student Object
(
    [name] => mike
    [age] => 19
)
Student Object
(
    [name] => mike
    [age] => 19
)
bool(true)
bool(true)

从上面的代码中,就能明显看出$student1$student2两个变量指向的是同一个对象,新手看到这可能并没有发现其中蹊跷,而且等值检测也没有问题啊(其实这里的等值检测是看不出什么的),这时,如果我继续修改$student2中的属性时,就能发现问题:

$student2->name = 'Jack';
$student2->age = 22;

print_r($student1);
print_r($student2);

// 输出
Student Object
(
    [name] => Jack
    [age] => 22
)
Student Object
(
    [name] => Jack
    [age] => 22
)

为什么会这样呢,我只是想修改$student2的属性,为什么$student1也改了,这就好比Dota里面的地卜师,只要逮到你一个分身,你就挂了。

地卜师

其实,看到这种情况,大概就能猜到PHP中对象的赋值都是通过引用操作,$student1$student2没有各自保留一份单独的副本,在内存中的分配大概就是这样的:

两个变量指向的是同一个内存地址,所以我们改变其中一个变量的属性是另一个也会变,但如果我们想要对两个变量做不同的操作并且互不影响该怎么办?

好在PHP提供了一个clone关键字来达到这个目的。

$student1 = new Student('mike', 19);
$student2 = clone $student1;

$student2->name = 'Jack';
$student2->age = 22;

print_r($student1);
print_r($student2);

// 输出
Student Object
(
    [name] => mike
    [age] => 19
)
Student Object
(
    [name] => Jack
    [age] => 22
)

通过clone复制后,现在$student1$student2就是两个不同的变量,修改互不影响。

关于__clone()方法

现在有这么一种情况,在复制对象时,想做一些修改操作,实际开发中,$id属性可能会与数据库表中某条记录一一对应,在复制之后,两个对象就指向数据库中的同一条记录了,那么使用__clone()就能控制复制时,哪些属性可以复制,哪些应该不复制或者置空。__clone()是个魔术方法,在对象上调用clone关键字时会自动调用。如下代码所示:

class Student
{
    public $id;
    public $name;
    public $age;

    function __construct($id, $name, $age) {
        $this->id = $id;
        $this->name = $name;
        $this->age = $age;
    }

    function __clone() {
        $this->id = 0;
    }
}

$student1 = new Student(1,'mike', 19);
$student2 = clone $student1;

print_r($student1);
print_r($student2);

// 输出
Student Object
(
    [id] => 1
    [name] => mike
    [age] => 19
)
Student Object
(
    [id] => 0
    [name] => mike
    [age] => 19
)

当在$student1上调用clone时,产生一个新的副本给$student2 ,这时$student2上就会自动调用__clone方法,使$id为0。

上面通过clone__clone()可以保证所有的基础数据类型可以被完全复制,但如果复制的对象中的属性也是一个对象时,复制后的两个对象都会引用同一个属性,修改时会互相影响,如下:

Class Score {
    public $english;
    public $math;

    function __construct($english, $math) {
        $this->english = $english;
        $this->math = $math;
    }
}

class Student
{
    public $id;
    public $name;
    public $age;
    public $score;

    function __construct($id, $name, $age, Score $score) {
        $this->id = $id;
        $this->name = $name;
        $this->age = $age;
        $this->score = $score;
    }

    function __clone() {
        $this->id = 0;
    }
}

$student1 = new Student(1,'mike', 19, new Score(80, 90));
$student2 = clone $student1;

// 我们需要修改$student1的英语成绩
$student1->score->english = 99;

//结果$student2的英语成绩也被修改了
echo $student2->score->english;

// 输出
99

上面这种情况并不是我们希望看到的,我们不想对象属性复制后被共享。解决方法就是在__clone()做做一些修改:

function __clone() {
      $this->id = 0;
      $this->score = clone $this->score;
}

// 输出
80

我所了解的PHP中对象复制大概就是这样,类似__clone()这样的魔术方法还有好几个,常见的还有:__set()__unset()__call()等,利用这些魔术方法可以实现更多复杂的操作,以后慢慢学习。

相关文章

  • PHP中对象的复制

    潜克隆(浅拷贝) 只能克隆对象的"非对象非资源"数据。但如果对象中属性存储的是对象类型,就可以看到克隆没有克隆对象...

  • PHP中的对象复制

    PHP中,=的作用都是将一个值复制给另一个(大多数编程语言都是一样),将=作用在基本数据类型上时,就直接进行了赋值...

  • 关于php clone

    php 对象复制,是复制对象的引用地址,因此使用 $objA = $objB 这种写法时,$objA与$objB会...

  • PHP的一些高级特性

    自定义__clone()复制对象 如上例,PHP4时代$second和$first是两个完全不同的对象,php5之...

  • PHP垃圾回收机制

    PHP中的 GC 在PHP中,没有任何变量指向这个对象时,这个对象就成为垃圾;PHP会将其在内存中销毁。这是PHP...

  • php Fatal error: Call to undefin

    1、在php.ini中extension=php_openssl.dll去掉前面的注释2、复制php安装目录中的:...

  • tp5修改分页设置,增加输入页码带参跳转笔记!

    复制Bootstrap.php改名BootstrapPage.php内容如下 把config.php分页配置中的b...

  • js中对象的复制,浅复制(浅拷贝)和深复制(深拷贝)

    在js中,我们经常复制一个对象,复制数据,那么就会有人问了,怎么复制,今天鹏哥就带来js中的复制方法。 JS中对象...

  • PHP 学习笔记(三)

    参考资料:PHP5 权威编程 PHP 中的类和对象 对象:万物皆对象; 类: 任何对象,都...

  • 深复制与浅复制

    浅复制 浅复制就是,直接把一个对象(源对象)的属性复制到另一个对象(目标对象)中,当然,如果当属性中包含引用类型的...

网友评论

    本文标题:PHP中的对象复制

    本文链接:https://www.haomeiwen.com/subject/fhmskqtx.html