2015年3月23日 星期一

PHP 使用 clone 複製物件

PHP 可以使用 "clone 物件" 的語法,複製一個物件,過程是採用淺複製(shallow copy)的方式,所以複製後,物件裡面的其他的物件,不會被複製到。

若想連裡面的物件也複製,可以設定 __clone方法,__clone 方法在複製新物件時會執行,所以可以設定複製時,要額外執行什麼動作。

範例 1:沒設定 __clone 方法,不會複製物件裡面的物件
class X1{
    public $v1 = 0;
}

class X2{
    public $v2 = 0;
    public $obj1;
    
    public function __construct() {
        $this->obj1  = new X1(); // 物件裡的物件
    }
}

$a = new X2();
$b = clone $a;

$b->v2 = 11; // 不會修改到 $a->v2
$b->obj1->v1 = 22; // $a->obj1->v1 也一起改變了
var_dump($a);
var_dump($b);
結果 $a->v2、$b->v2 分別為 0、11,表示 $a、$b 是不同物件。
但 $a->obj1->v1、$b->obj1->v1 都變成 22,
表示 $a->obj1 和 $b->obj1 還是指向同一個物件,因為 clone 是淺複製。
object(X2)#1 (2) {
  ["v2"]=>
  int(0)
  ["obj1"]=>
  object(X1)#2 (1) {
    ["v1"]=>
    int(22)
  }
}
object(X2)#3 (2) {
  ["v2"]=>
  int(11)
  ["obj1"]=>
  object(X1)#2 (1) {
    ["v1"]=>
    int(22)
  }
}


範例 2:設定 __clone 方法,在 __clone ,再複製一次包含的物件。
class X1{
    public $v1 = 0;
}

class X2{
    public $v2 = 0;
    public $obj1;
    
    public function __construct() {
        $this->obj1  = new X1(); // 物件裡的物件
    }
    
    //當 clone 發生時會執行
    public function __clone(){
        $this->obj1 = clone $this->obj1;
    }
}

$a = new X2();
$b = clone $a;

$b->v2 = 11; // 不會修改到 $a->v2
$b->obj1->v1 = 22; // 不會修改到 $a->obj1->v1
var_dump($a);
var_dump($b);
結果 $a->obj1->v1、$b->obj1->v1 分別為 0、22,表示 $a->obj1 和 $b->obj1 是不同物件。
object(X2)#1 (2) {
  ["v2"]=>
  int(0)
  ["obj1"]=>
  object(X1)#2 (1) {
    ["v1"]=>
    int(0)
  }
}
object(X2)#3 (2) {
  ["v2"]=>
  int(11)
  ["obj1"]=>
  object(X1)#4 (1) {
    ["v1"]=>
    int(22)
  }
}

參考:
http://php.net/manual/en/language.oop5.cloning.php

沒有留言:

張貼留言