zoukankan      html  css  js  c++  java
  • php 对象克隆 clone

    php 对象复制,是复制对象的引用地址,因此使用 $objA = $objB 这种写法时,$objA与$objB会指向相同的内存地址。当$objA 发生变化时,$objB也会受到影响。
    如果我们要$objA对象复制为$objB对象,复制之后,$objA有什么变化,都不会影响$objB。即$objA与$objB是两个独立的对象,但$objB的初始值是由$objA创建的,比较高效的做法是使用clone()方法。
    $objB = clone $objA;
    $objB的值是在$objA基础加$objA事例对象里clone()方法改变后的实例。
    当对象被复制后,所有的属性中的引用保持不变,指向原来的变量,如果定义了__clone()方法,则新创建的对象中的__clone()方法会被调用,可用于修改属性的值。

    例子1:clone 对象

    <?php
    class subclass{
    
    	private $name;
    	private $age;
    
    	public function __construct(){
    		$this->name = 'fdipzone';
    		$this->age = '30';
    	}
    
    	public function __clone(){
    		$this->name = 'xfdipzone';
    		$this->age = '29';
    	}
    
    }
    
    
    class myclass{
    
    	public $p1;
    	public $p2;
    
    	public function __construct(){
    
    	}
    
    	public function __clone(){
    		$this->p1 = clone $this->p1;
    	}
    
    }
    
    $obj = new myclass();
    $obj->p1 = new subclass();
    $obj->p2 = new subclass();
    
    $obj2 = clone $obj;
    
    echo '<pre>';
    echo 'obj<br>';
    var_dump($obj);
    echo '<br>obj2<br>';
    var_dump($obj2);
    echo 'ok';
    echo '</pre>';
    
    ?>
    上例将输出:
    obj
    object(myclass)#1 (2) {
      ["p1"]=>
      object(subclass)#2 (2) {
        ["name":"subclass":private]=>
        string(8) "fdipzone"
        ["age":"subclass":private]=>
        string(2) "30"
      }
      ["p2"]=>
      object(subclass)#3 (2) {
        ["name":"subclass":private]=>
        string(8) "fdipzone"
        ["age":"subclass":private]=>
        string(2) "30"
      }
    }
    
    obj2
    object(myclass)#4 (2) {
      ["p1"]=>
      object(subclass)#5 (2) {
        ["name":"subclass":private]=>
        string(9) "xfdipzone"
        ["age":"subclass":private]=>
        string(2) "29"
      }
      ["p2"]=>
      object(subclass)#3 (2) {
        ["name":"subclass":private]=>
        string(8) "fdipzone"
        ["age":"subclass":private]=>
        string(2) "30"
      }
    }
    可以见到,$obj2 clone $obj,$obj->p1 clone $obj->p1,执行了 __clone()方法。而在__clone方法中,对p1的name与 age属性进行修改,因此p1的name与age 发生变化。而p2因为没有执行clone()方法,所以新复制出来的$obj2->p2的属性与 $obj->p2一样。

    例子2:clone对象,但部分属性引用保持不变。

    <?php
    
    class myclass{
    
    	public $num = null;
    	public $msg = null;
    
    	public function __construct(){
    		$this->num = & $this->num;
    		$this->msg = 'OK';
    	}
    
    	public function __clone(){
    		$this->num = 2;	
    	}
    }
    
    $obj = new myclass();
    $obj->num = 1;
    
    echo 'print obj values<br>';
    var_dump($obj);
    echo '<br><br>';
    
    $obj2 = clone $obj;
    
    echo 'clone obj to obj2<br>';
    echo 'obj->num:'.$obj->num.'<br>';
    echo 'obj->msg:'.$obj->msg.'<br>';
    echo 'obj2->num:'.$obj2->num.'<br>';
    echo 'obj2->msg:'.$obj2->msg.'<br><br>';
    
    $obj2->num = 3;
    $obj2->msg = 'Yes';
    
    echo 'set obj2->num=3, obj2->msg=Yes<br>';
    echo 'obj->num:'.$obj->num.'<br>';
    echo 'obj->msg:'.$obj->msg.'<br>';
    echo 'obj2->num:'.$obj2->num.'<br>';
    echo 'obj2->msg:'.$obj2->msg.'<br><br>';
    
    ?>
    上例将输出:
    print obj values
    object(myclass)#1 (2) { ["num"]=> &int(1) ["msg"]=> string(2) "OK" }
    
    clone obj to obj2
    obj->num:2
    obj->msg:OK
    obj2->num:2
    obj2->msg:OK
    
    set obj2->num=3, obj2->msg=Yes
    obj->num:3
    obj->msg:OK
    obj2->num:3
    obj2->msg:Yes
    
    因$this->num = &$this->num,因此clone()之后,新对象的$this->num都是引用旧对象的内存地址。因此旧对象这个属性发生变化,新对象这个属性也会发生变化,实现了某些属性的引用保持不变。
    而$this->msg并不是地址引用,因此,新对象的msg发生变化,不会影响到旧对象。


    注意:$this->num = & $this->num 使用对象属性地址引用时,在clone之前不能echo/print这个属性,否则地址引用会失效。

    上例中,如果在$obj2 = clone $obj前加上,echo $obj->num; 则会使地址引用实效,即$obj2->num发生改变,$obj->num并不会发生改变。


  • 相关阅读:
    Two Sum II
    Subarray Sum
    Intersection of Two Arrays
    Reorder List
    Convert Sorted List to Binary Search Tree
    Remove Duplicates from Sorted List II
    Partition List
    Linked List Cycle II
    Sort List
    struts2结果跳转和参数获取
  • 原文地址:https://www.cnblogs.com/fdipzone/p/3715075.html
Copyright © 2011-2022 走看看