Home > php教程 > php手册 > body text

[PHP] Object duplication (copy) and __clone() method

WBOY
Release: 2016-09-01 00:00:45
Original
1388 people have browsed it

Reference link:

1. php.net official website documentation - object copy

When to use it? Excerpted from php.net:

In most cases, we do not need to completely copy an object to obtain its properties. But there is one case where it is really needed: if you have a GTK window object that holds window-related resources. You may want to copy a new window, keeping all the same properties as the original window, but it must be a new object (because if it is not a new object, changes in one window will affect the other window). There is another situation: if object A stores a reference to object B, when you copy object A, and you want the object used in it to be no longer object B but a copy of B, then you must get a copy of object A. .

Try to use the simplest "="

The first thing to make clear is: PHP objects are stored with an identifier, so the direct "assignment" behavior to the object is equivalent to "passing by reference"

<?php

function dump($var){
    var_dump($var);
    echo "<br/>";
}

class A{
    private $a;
    protected $b;
    public $c;

    public function d(){
        echo "A -> d";
    }
}

$a1 = new A();
$a2 = $a1;
$a3 = new A();
dump($a1);
dump($a2);
dump($a3);
Copy after login

The output result is:

object(A)#1 (3) { ["a":"A":private]=> NULL ["b":protected]=> NULL ["c"]=> NULL } 
object(A)#1 (3) { ["a":"A":private]=> NULL ["b":protected]=> NULL ["c"]=> NULL } 
object(A)#2 (3) { ["a":"A":private]=> NULL ["b":protected]=> NULL ["c"]=> NULL } 
Copy after login

It can be noticed that #n as the object identifier shows that $a1 and $a2 actually point to the same object, while $a3 is another object

So, if you need to copy an identical and brand-new object, you cannot copy it directly through =, otherwise changing $a1->a is equivalent to modifying $a2->a.

Shallow copy

In PHP5, there is a magic method __clone() in the class, which will be automatically called when used with the clone keyword and object (if not explicitly defined, an empty method will be called).

The function of the clone keyword is to copy an object to form a "shallow copy" of the object, and then assign it to the new object. At this time, the object identifier is different!

<?php

function dump($var){
    var_dump($var);
    echo "<br/>";
}

class B{
    public $d;
}

class A{
    public $a;
    public $b;

    public function d(){
        echo "A -> d";
    }
}

$a1 = new A();
$a1->a = 123;
// 这里对象属性的值是一个对象示例,其实就是存储了对象标识符。使用clone关键字生成的拷贝中的b属性仍然指向旧对象的b属性指向的对象,这是"浅拷贝"出现的问题。如果需要指向一个新的对象,必须"深拷贝"
$a1->b = new B();

// PHP 5 only
$a2 = clone $a1;

dump($a1);
dump($a2);
Copy after login

The output result is:

object(A)#1 (2) { ["a"]=> int(123) ["b"]=> object(B)#2 (1) { ["d"]=> NULL } } 
object(A)#3 (2) { ["a"]=> int(123) ["b"]=> object(B)#2 (1) { ["d"]=> NULL } } 
Copy after login

As you can see, $a1 and $a2 are obviously two different objects (the object identifiers are different). But one thing to note is that the object identifiers pointed to by "b" are both #2, which proves that the two objects are the same. This is the "flaw" of "shallow copy" - but sometimes these two objects do need The same, so PHP's clone defaults to "shallow copy".

Why is it called shallow copy?

Because when copying, all attributes are "passed by value", and the b attribute above stores the object identifier, so it is equivalent to "passing by reference". This is not a complete copy, so it is called "Shallow copy".

Deep copy

As mentioned above, when using the clone keyword, the __clone() method of the old object will be automatically called (and then the copied object will be returned), so you only need to rewrite the __clone() method in the corresponding class to make the returned The "pass-by-reference" property in an object points to another new object. The following is an example (you can compare the example of "shallow copy", which actually requires more steps to rewrite __clone()):

<?php

function dump($var){
    var_dump($var);
    echo "<br/>";
}

class B{
    public $d;
}

class A{
    public $a;
    public $b;

    public function d(){
        echo "A -> d";
    }

    public function __clone(){
        // clone自己
        $this->b = clone $this->b;
    }
}

$a1 = new A();
$a1->a = 123;
// 这里对象属性的值是一个对象示例,其实就是存储了对象标识符。使用clone关键字生成的拷贝中的b属性仍然指向旧对象的b属性指向的对象,这是"浅拷贝"出现的问题。如果需要指向一个新的对象,必须"深拷贝"
$a1->b = new B();

// PHP 5 only
$a2 = clone $a1;

dump($a1);
dump($a2);
Copy after login

The result is different, pay attention to the object identifier of the b attribute:

object(A)#1 (2) { ["a"]=> int(123) ["b"]=> object(B)#2 (1) { ["d"]=> NULL } } 
object(A)#3 (2) { ["a"]=> int(123) ["b"]=> object(B)#4 (1) { ["d"]=> NULL } } 
Copy after login

source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Recommendations
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template