0

以下は単純化されたコードです。

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));

このコードには 2 つの問題があります。おそらくもっとある;)

  1. var1 の再割り当てが $foo に影響しているようです。$foo->a を $a に渡した後は、そうではないと思います。

  2. コンストラクトでは、$foo を $this->foo に割り当てましたが、ループごとにその値が変更されます。$this->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>";
    }

}

バズのクラス

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
4

1 に答える 1

1

あなたが見ている行動は正常です。オブジェクトを PHP の変数に割り当てるときは、値ではなく参照を渡します。参照ではなくコピーが必要な場合は、クローンを作成する必要があります。

たとえば、次のシナリオでは:

$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;
        }

完全な編集については、上記のクラスを参照してください。

于 2012-07-02T23:22:00.887 に答える