递归调用后PHP成员更改

时间:2012-07-02 23:08:15

标签: php class recursion member

这是一个简单的代码:

Class Bar
{
    static $foo;

    public function __construct(Foo $foo)
    {
        $this->foo = $foo;
        $this->loop($foo,1);
    }

    public function loop(Foo $foo, $index)
    {   

        $a = $foo->a;
        if ($index < 3)
        {
            $a[$index]->var2 += $a[$index]->var1;
            $a[$index]->var1 = 0;
            $foo->dump();
            $this->foo->dump();

            $this->loop(new Foo($a),++$index);
        }
    }
}

$p = array(
      new Baz(100,200),
      new Baz(300,400),
      new Baz(400,200),
      new Baz(600,400)
    );

new Bar(new Foo($p));

此代码存在两个问题。也许更多;)

  1. 看起来var1的重新分配对$ foo有影响。我希望在我将$ foo-&gt; a传递给$ a后它没有。

  2. 在构造中我将$ foo分配给$ this-&gt; foo,但在每次循环后它都会更改其值。有人能指出$ this-&gt; foo的价值在哪里变化?

  3. 更多信息 Foo类的定义

    Class Foo
    {
        public $a;
        public function __construct($a)
        {
            $this->a = $a;
        }
        public function dump($title="")
        {
            echo "<br/>================".$title."=============================";
            echo "<table>";
            for ($i=0; $i<sizeof($this->a); $i++)
            {
                echo "<tr>";
                echo "<td>" . $this->a[$i]->var1 . "</td>";
                echo "<td>" . $this->a[$i]->var2 . "</td>";
                echo "</tr>";
    
            }
            echo "</table>";
        }
    
    }
    

    Baz班

    Class Baz
    {
        public $var1;
        public $var2;
        public function __construct($var1, $var2)
        {
            $this->var1=$var1;
            $this->var2=$var2;
        }
    
    }
    

    转储的结果:

    ================IM foo dump=============================
    100 200
    0   700
    400 200
    600 400
    
    ================Im $this->foo dump=====================
    100 200
    0   700
    400 200
    600 400
    
    ================IM foo dump=============================
    100 200
    0   700
    0   600
    600 400
    
    ================Im $this->foo dump======================
    100 200
    0   700
    0   600
    600 400
    

1 个答案:

答案 0 :(得分:1)

您看到的行为是正常的。在PHP中为变量分配对象时,传递引用,而不是值;如果您想要复制而不是引用,则必须create a clone

例如,在以下场景中:

$blub = new Bar();
$a = $blub;
$b = $blub;
$c = $blub;

$ a,$ b,$ c只是“别名”可以这么说,那指向$ blub;意味着设置$ a的任何成员对$ blub有直接影响,因此$ b和$ c也是如此。

通过使用关键字clone,您可以获得所需的结果:

$blub = new Bar();
$a = clone $blub;
$b = clone $blub;
$c = clone $blub;

这里我们明确创建了独立副本,因此修改$ a的内容不会改变$ blub,$ b或$ c。

最后,您的示例类如何实现克隆以处理独立对象:

Class Bar
{
    public $foo;

    public function __construct(Foo $foo)
    {
        $this->foo = $foo;
        $this->loop(clone $foo, 1);
    }

    public function loop(Foo $foo, $index)
    {   
        $a = array();

        foreach($foo->a as $key => $subobject) {
            $a[$key] = clone $subobject;
        }

        if ($index < 3)
        {
            $a[$index]->var2 += $a[$index]->var1;
            $a[$index]->var1 = 0;
            $foo->dump();
            $this->foo->dump();

            $this->loop(new Foo($foo->a),++$index);
        }
    }
}


new Bar(new Foo($p));

更新

简单地克隆$ foo是不够的,因为传递了一个对象数组:

$p = array(
      new Baz(100,200),
      new Baz(300,400),
      new Baz(400,200),
      new Baz(600,400)
    );

即使您克隆承载数组的对象,数组中的对象本身仍然指向相同的对象,因为数组只是持有引用;克隆对象时,将复制数组成员及其内容,包括引用。需要一点时间来了解引用和值的概念,但最终你会看到一切都像拼图:)

无论如何,在这种特殊情况下,必须在使用它们之前克隆数组中的对象,这可以通过Bar :: loop函数中的以下循环轻松实现:

        foreach($a as $key => $subobject) {
            $a[$key] = clone $subobject;
        }

请参阅上面的课程以了解完整的修改。