在__clone中通过引用传递

时间:2013-10-26 17:03:08

标签: php clone pass-by-reference

在我的__clone方法中,我通过引用将一个变量分配给另一个变量。克隆之后,我期望发生的是,当我为一个对象更改此变量时,它会在另一个对象中更改。但这似乎并没有发生。

我的代码:

class a {
    var $a;

    function a($var = NULL) {
        if (isset($var)) {
            $this->a = $var;
        }
    }

    function __clone() {
        $temp = new a();
        $temp->a = &$this->a;
        return $temp;
    }
}

$a = new a('test');
$b = clone $a;
$b->a = 'zzz';

echo $a->a;
echo "\r\n";
echo $b->a;

输出是这样的:

test
zzz

我希望它是这样的:

zzz
zzz

3 个答案:

答案 0 :(得分:1)

如果我在克隆时没有弄错,那么引用就会被删除(我认为这是一种内部机制),它会使你想要实现的内容混淆,因为你可以这样做:

$a = new a('test');
$b = $a;
$b->a = 'zzz';

echo $a->a;
echo "\r\n";
echo $b->a;

引用:“...您要创建此其他对象的新实例,以便副本具有自己的单独副本。”

<强>来源: http://php.net/manual/ro/language.oop5.cloning.php

答案 1 :(得分:1)

那是因为__clone()的返回值被忽略了。您可以看到,如果您将$temp->a = &$this->a;行更改为$temp->a = 'CLONED';,然后只需echo $b->a;

因此,您无法更改克隆的结果对象。

答案 2 :(得分:1)

在调用__clone方法之前,PHP已经按值复制了所有属性。 PHP完成克隆对象后,将调用您的方法。因此,您在该方法中访问的任何属性都是值副本。文档说明:

  

克隆对象时,PHP 5将执行所有对象属性的浅表副本。任何引用其他变量的属性都将保留引用。

     

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

您可以在this page的第二段找到此信息。

虽然这不是一个非常漂亮的解决方法,但您可以重命名__clone方法。然后,您可以使用该方法克隆您的对象,虽然这当然不再是实际的克隆,因为它不使用接口进行克隆。