这是一个简单的代码:
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));
此代码存在两个问题。也许更多;)
看起来var1的重新分配对$ foo有影响。我希望在我将$ foo-&gt; a传递给$ a后它没有。
在构造中我将$ foo分配给$ this-&gt; foo,但在每次循环后它都会更改其值。有人能指出$ this-&gt; foo的价值在哪里变化?
更多信息 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
答案 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;
}
请参阅上面的课程以了解完整的修改。