PHPにはリファレンス(参照)というポインタのようなものがあります。クラスオブジェクトにも使えるんですが意味がありません。
クラスオブジェクトの変数代入は参照渡しで、それはリファレンスと同じ動きだから。関数のパラメータでも同じ。
ただリファレンスとオブジェクト代入の内部のしくみは全くの別物。
PHPのリファレンスはポインタのような動きをするんですが内部は違うメカニズムです。じっさい、ポインタというより変数のハードリンクのようなものと説明される。
ここではリファレンスの詳細な説明は割愛して、クラスオブジェクトではリファレンスに意味がないところにスポットを当てます。
まず、このコードを見てください。
<?php
class Test {
public $value;
}
$test1 = new Test();
$test1->value = 'default';
$test2 = $test1;
$test2->value = 'change';
var_dump($test1);
var_dump($test2);
数値や文字列、配列の変数は新たな変数に代入すると、それぞれ独立しています。$test1 と $test2 の内容はちがうはず。
でも、クラスオブジェクトでは、$test1 と $test2 は同じものになります。実行結果はこうなります。
object(Test)#1 (1) {
["value"]=>
string(6) "change"
}
object(Test)#1 (1) {
["value"]=>
string(6) "change"
}
$test2 での変更内容が $test1 にも反映されました。これがクラスオブジェクトのしくみ。
クラスオブジェクトは、その内容が変数に入ってるわけではありません。変数が持っているのはオブジェクトに割り当てられたIDのみ。
代入された $test2 にはそのIDがコピーされるので、結果的に同じオブジェクトを参照することになります。
var_dump()の出力結果で、オブジェクトの後ろに "#1" になっているところがID。
これからも $test1 と $test2 が同じものだというのが分かる。
参照と言ってもリファレンスとは内部メカニズムが全くの別物。(ややこしい。)
この動き、まさしくクラス以外の変数ではリファレンスですよね?
今度はクラスオブジェクトを関数のパラメータに渡してみましょう。
<?php
class Test {
public $value;
}
function test( $obj ) {
$obj->value = 'change';
}
$test = new Test();
$test->value = 'default';
test($test);
var_dump($test);
object(Test)#1 (1) {
["value"]=>
string(6) "change"
}
test() 内で変更した内容が $test にも反映されました。
関数にパラメータで渡すということは $obj = $test と同じです。
(ただし、$obj は関数内だけで通用する変数。)
普通は考えられないですよね? 関数内での変更が全体に影響します。
JavaとかC++のオブジェクト指向言語をやってる人には当たり前じゃんという話なんですが、PHPでクラスを使わないプログラミングをするのに慣れてしまっている人は要注意。
これもまさしくリファレンスの動きですよね?
しつこいようですが、これも動きは一緒でも内部のメカニズムは全くの別物です。
クラスオブジェクトは参照渡しと言われるんですが、もちろんリファレンスとはちがう。
もう1回言っとこう。ややこしい。
リファレンスはPHP独自の考え方で、オブジェクトの変数への代入は、Javaなどのオブジェクト指向言語と同じしくみをPHPに導入しています。
オブジェクトの代入(=)はシャローコピーと言う。
PHP公式ドキュメント