PHP7.4.1におけるインスタンスの複製について。
//クラス
class Ca {
//プロパティ
protected float $ia; //実数型のプロパティ
public int $ib; //パブリックなプロパティ
//コンストラクター(メソッド)
public function __construct($a) {
$this->ia = 1 + ($a / 100); //引数を%に変換して1を加算して$iaに代入
}
//ゲッター(メソッド)
public function getIa($b): int {
return $b * $this->ia; //引数の税込み価格を演算
}
}
//実行
$ca = new Ca(10); //Caクラスのインスタンスの作成
$ca->ib = 1234; //$caインスタンスにおいてCaクラスの$ibに1234を代入
$ca2 = $ca; //$caインスタンスの複製($caと同期)
echo $ca2->ib, "\n"; //1234 ← $ca2は$caの参照渡しとなってしまっている
$cb = new Ca(10); //2つ目のCaクラスのインスタンスの新規作成
echo $cb->ib, "\n"; //ibはまだ初期化されてないのでFatal Errorがでる
$ca3 = clone($ca); //cloneを使った$caインスタンスの複製(初期値のみ$caと同期)
echo $ca3->ib, "\n"; //ibはまだ初期化されてないのでFatal Errorがでる
$ca->ib = 5678; //$caのibの値を再代入
echo $ca2->ib, "\n"; //5678 ← $ca2は$caの参照渡しなのでこうなる
echo $ca3->ib, "\n"; //1234 ← $ca3はcloneによって$caともう同期してないのでこうなる
クラスのインスタンスを作成するには2つの方法があります。
1つ目の方法は新規作成で、2つ目はの方法は既存のインスタンスの複製です。
インスタンスの新規作成には1つのパターンしかなく、$〇〇 = new〇〇(); と記述すればOKです。
しかしインスタンスの複製については、2つの異なるパターンが存在します。
〇複製のパターン1:代入元と同期したインスタンス
複製の1つ目のパターンは、既存のインスタンスをそのまま別の変数に代入してやる方法です。
たとえば上記スクリプトだと、Caクラスのインスタンスである$caをただ代入しているだけの$ca2がこのパターンに該当します。
この方法で作成したインスタンスは、代入元のインスタンスとデータが完全に同期しています。
なのでこの複製された$ca2は独立した1つのインスタンスとしてあつかうことができません。
つまり存在価値のないインスタンスというわけです。
だって代入元の$caの参照渡し状態なわけですから、それならば$caがあればすべてこと足りてしまいますからね。
〇複製パターン2:代入元と非同期のインスタンス
複製の2つ目のパターンは、clone()を使って既存のインスタンスからそのインスタンとは非同期の別のインスタンスを作る方法です。
この方法で複製したインスタンスは、複製時のデータ(プロパティの値)はすべて複製元のインスタンスのものと同じです。
しかしそこから先はもう複製元のインスタンスとは非同期化されていて、完全に別のインスタンスとしてあつかわれます。
なので上記スクリプトのように複製元である$caインスタンスからibプロパティに値を再代入したとしても、cloneで複製した$ca3の値には何の影響もありません。
以上です。