PHP - 对象克隆



像 “$obj1 = $obj2” 这样的 PHP 语句仅仅创建了对内存中同一对象的另一个引用。因此,属性的更改会反映在原始对象和副本对象中。PHP 中的 **clone** 关键字创建对象的浅拷贝。

$obj2 = $obj1

原始对象的更改不会反映在浅拷贝中。

示例

请看以下示例:

<?php
   class foo {
      var $var1 = 'Hello';
   }
   $x = new foo();
   $y = $x;		# reference copy
   echo $x->var1 . " " . $y->var1 . PHP_EOL;

   $x->var1 = "Hello World";
   echo $x->var1 . " " . $y->var1 . PHP_EOL;
?>

它将产生以下 **输出**:

Hello Hello
Hello World Hello World

在第一种情况下,**$y** 只是 **$x** 的引用副本。因此,**var1** 属性的任何更改都会反映在两者中。

但是,如果我们将 **$y** 声明为 **$x** 的克隆,则原始对象的任何更改都不会反映在其浅拷贝中。

示例

请看以下示例:

<?php
   class foo {
      var $var1 = 'Hello World';
   }

   $x = new foo();

   # shallow copy
   $y = clone $x;
   echo $x->var1 . " " . $y->var1 . PHP_EOL;

   $x->var1 = "Hello PHP";
   echo $x->var1 . " " . $y->var1 . PHP_EOL;
?>

它将产生以下 **输出**:

Hello World Hello World
Hello PHP Hello World

示例

在以下代码中,**myclass** 的一个属性是 address 类的对象。通过赋值复制 myclass 的对象。其嵌入的 address 对象的值的任何更改都将反映在两个对象中,但 name 属性的更改不会影响克隆的对象。

<?php
   class address {
      var $city="Nanded";
      var $pin="431601";
      function setaddr($arg1, $arg2) {
         $this->city=$arg1;
         $this->pin=$arg2;
      }
   }
   class myclass {
      var $name="Raja";
      var $obj;
      function setname($arg) {
         $this->name=$arg;
      }
   }

   $obj1=new myclass();
   $obj1->obj=new address();
   echo "original object\n";
   print_r($obj1);
   echo "\n";

   $obj2=$obj1;		# reference copy
   $obj1->setname("Ravi");
   $obj1->obj->setaddr("Mumbai", "400001");
   echo "after change: Original object\n";
   print_r($obj1);
   echo "\nCopied object\n";
   print_r($obj2);
?>

它将产生以下 **输出**:

original object
myclass Object
(
   [name] => Raja
   [obj] => address Object
   (
      [city] => Nanded
      [pin] => 431601
   )
)

after change: Original object
myclass Object
(
   [name] => Ravi
   [obj] => address Object
   (
      [city] => Mumbai
      [pin] => 400001
   )
)

Copied object
myclass Object
(
   [name] => Ravi
   [obj] => address Object
   (
      [city] => Mumbai
      [pin] => 400001
   )
)

使用 "clone" 关键字

在浅拷贝中,原始对象的任何引用其他变量的属性都将保持引用。clone 关键字不会复制被复制对象的包含对象。

现在我们创建 myclass 对象的克隆,以便 **$obj2** 是 **$obj1** 的克隆。我们将 **$obj1** 的 name 属性从 **Raja** 更改为 **Ravi**,并修改嵌入的 address 对象。属性更改将不会反映在其克隆中,但引用的 address 对象将被更改。

示例

请看以下示例:

<?php
   class address {
      var $city="Nanded";
      var $pin="431601";
      function setaddr($arg1, $arg2) {
         $this->city=$arg1;
         $this->pin=$arg2;
      }
   }
   class myclass {
      var $name="Raja";
      var $obj;
      function setname($arg) {
         $this->name=$arg;
      }
   }
   $obj1=new myclass();
   $obj1->obj=new address();
   echo "original object\n";
   print_r($obj1);
   echo "\n";

   $obj2=clone $obj1;		# clone copy
   $obj1->setname("Ravi");
   $obj1->obj->setaddr("Mumbai", "400001");
   echo "after change: Original object\n";
   print_r($obj1);
   echo "\nCopied object\n";
   print_r($obj2);
?>

它将产生以下 **输出**:

original object
myclass Object
(
   [name] => Raja
   [obj] => address Object
   (
      [city] => Nanded
      [pin] => 431601
   )
)

after change: Original object
myclass Object
(
   [name] => Ravi
   [obj] => address Object
   (
      [city] => Mumbai
      [pin] => 400001
   )
)

Copied object
myclass Object
(
   [name] => Raja
   [obj] => address Object
   (
      [city] => Mumbai
      [pin] => 400001
   )
)

使用 __clone() 方法

clone 关键字创建对象的浅拷贝。当克隆对象时,PHP 将执行其所有属性的浅拷贝。任何引用其他变量的属性都将保持引用。因此,对原始对象所做的任何更改也将在克隆对象中出现。

如果您希望阻止复制的对象自动更新,我们需要使用 __clone() 方法创建对象的深拷贝。它是 PHP 中的一种魔术方法。

克隆完成后,如果定义了 __clone() 方法,则将调用新创建的对象的 __clone() 方法,以允许更改任何需要更改的必要属性。

示例

在上面的示例中,我们有一个 myclass 的对象,它的一个属性 $obj 持有对 address 类对象的引用。为了实现深拷贝,我们在 myclass 中覆盖了 __clone() 魔术方法。

<?php
   class address {
      var $city="Nanded";
      var $pin="431601";
      function setaddr($arg1, $arg2) {
         $this->city=$arg1;
         $this->pin=$arg2;
      }
   }
   class myclass {
      var $name="Raja";
      var $obj;
      function setname($arg) {
         $this->name=$arg;
      }
      public function __clone() {
         $this->obj = clone $this->obj ;
      }
   }
   $obj1=new myclass();
   $obj1->obj=new address();
   echo "original object\n";
   print_r($obj1);
   echo "\n";

   $obj2=clone $obj1;		# cloned deep copy
   $obj1->setname("Ravi");
   $obj1->obj->setaddr("Mumbai", "400001");
   echo "after change: Original object\n";
   print_r($obj1);
   echo "\nCloned object\n";
   print_r($obj2);
?>

您现在将看到原始对象中的更改(我们将更改地址属性)不会反映在克隆对象中,如下所示的 **输出**:

original object
myclass Object
(
   [name] => Raja
   [obj] => address Object
   (
      [city] => Nanded
      [pin] => 431601
   )
)

after change: Original object
myclass Object
(
   [name] => Ravi
   [obj] => address Object
   (
      [city] => Mumbai
      [pin] => 400001
   )
)

Cloned object
myclass Object
(
   [name] => Raja
   [obj] => address Object
   (
      [city] => Nanded
      [pin] => 431601
   )
)
广告

© . All rights reserved.