Php 简明教程
PHP - Cloning Objects
诸如“$obj1 = $obj2”的 PHP 语句只是创建对内存中同一对象的另一个引用。因此,属性的更改同时反映在原始对象和复制的对象中。PHP 中的 clone 关键字创建对象的浅拷贝。
$obj2 = $obj1
原始对象中的更改不会反映在浅拷贝中。
Example
请看以下示例:
<?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;
?>
它将生成以下 output −
Hello Hello
Hello World Hello World
在第一种情况下, $y 只是 $x 的引用副本。因此, var1 属性的任何更改都会反映在两者中。
但是,如果我们将 $y 声明为 $x 的克隆,则原始对象中的任何更改都不会反映在其浅拷贝中。
Example
请看以下示例:
<?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;
?>
它将生成以下 output −
Hello World Hello World
Hello PHP Hello World
Example
在以下代码中, myclass 的属性之一是作为地址类对象的属性。myclass 的一个对象被赋值复制。其嵌入地址对象的任何值的变化会反映在两个对象中,但是名称属性的变化不会体现在克隆对象中。
<?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);
?>
它将生成以下 output −
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
)
)
Using the "clone" Keyword
在浅表副本中,任何是对其他变量引用的原始对象的属性都将保持引用。clone 关键字不会复制复制对象的包含对象。
我们现在创建 myclass 对象的克隆,以便 $obj2 是 $obj1 的克隆。我们将 $obj1 的 name 属性从 Raja 更改为 Ravi ,然后修改嵌入地址对象。属性更改不会反映在其克隆中,但是引用的地址对象将更改。
Example
请看以下示例:
<?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);
?>
它将生成以下 output −
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
)
)
Using __clone() Method
clone 关键字创建对象的浅表副本。克隆对象后,PHP 将对所有对象的属性执行浅表副本。是对其他变量引用的任何属性都将保持引用。因此,对原始对象执行的任何更改也将出现在克隆对象中。
如果您希望防止复制的对象自动更新,则需要使用 __clone() 方法创建对象的深表副本。它是 PHP 中的魔术方法之一。
一旦克隆完成,如果定义了 _clone() 方法,系统就会调用新创建对象的 _clone() 方法,以允许需要更改的任何必要属性。
Example
在上述示例中,我们有一个 myclass 对象,其中一个属性 $obj 保存对地址类的对象的引用。要实现深表副本,我们会覆盖 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);
?>
您现在会看到原始对象(我们更改地址属性)中的更改不会反映在克隆对象中,如下面的 output 所示。
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
)
)