참고링크:
1. php.net 공식 웹사이트 문서 - 객체 복사
언제 사용되나요? php.net에서 발췌:
대부분의 경우 개체의 속성을 얻기 위해 개체를 완전히 복사할 필요는 없습니다. 하지만 이것이 정말로 필요한 경우가 하나 있는데, 창 관련 리소스를 담고 있는 GTK 창 객체가 있는 경우이다. 원래 창과 동일한 속성을 모두 유지하면서 새 창을 복사할 수 있지만 새 개체여야 합니다(새 개체가 아닌 경우 한 창의 변경 사항이 다른 창에 영향을 미치기 때문입니다). 또 다른 상황이 있습니다. 객체 A가 객체 B에 대한 참조를 저장하는 경우 객체 A를 복사하고 여기에 사용된 객체가 더 이상 객체 B가 아니라 B의 복사본이 되도록 하려면 객체 A의 복사본을 가져와야 합니다. .
가장 간단한 "="
을 사용해 보세요.먼저 분명히 해야 할 점은 PHP 개체는 식별자와 함께 저장되므로 개체에 대한 직접적인 "할당" 동작은 "참조에 의한 전달"과 동일하다는 것입니다.
<?php function dump($var){ var_dump($var); echo "<br/>"; } class A{ private $a; protected $b; public $c; public function d(){ echo "A -> d"; } } $a1 = new A(); $a2 = $a1; $a3 = new A(); dump($a1); dump($a2); dump($a3);
출력 결과는 다음과 같습니다.
object(A)#1 (3) { ["a":"A":private]=> NULL ["b":protected]=> NULL ["c"]=> NULL } object(A)#1 (3) { ["a":"A":private]=> NULL ["b":protected]=> NULL ["c"]=> NULL } object(A)#2 (3) { ["a":"A":private]=> NULL ["b":protected]=> NULL ["c"]=> NULL }
객체 식별자인 #n은 $a1과 $a2가 실제로 동일한 객체를 가리키는 반면 $a3은 다른 객체임을 나타냅니다.
따라서 동일하고 새로운 객체를 복사해야 하는 경우 =를 통해 직접 복사할 수 없습니다. 그렇지 않으면 $a1->a를 변경하는 것은 $a2->a를 수정하는 것과 같습니다.
얕은 카피
PHP5에는 클래스에 매직 메소드 __clone()이 있는데, 이는 clone 키워드 및 객체와 함께 사용될 때 자동으로 호출됩니다(명시적으로 정의되지 않은 경우 빈 메소드가 호출됩니다).
clone 키워드의 기능은 개체를 복사하여 개체의 "얕은 복사본"을 형성한 다음 이를 새 개체에 할당하는 것입니다. 이때 개체 식별자는 다릅니다.
<?php function dump($var){ var_dump($var); echo "<br/>"; } class B{ public $d; } class A{ public $a; public $b; public function d(){ echo "A -> d"; } } $a1 = new A(); $a1->a = 123; // 这里对象属性的值是一个对象示例,其实就是存储了对象标识符。使用clone关键字生成的拷贝中的b属性仍然指向旧对象的b属性指向的对象,这是"浅拷贝"出现的问题。如果需要指向一个新的对象,必须"深拷贝" $a1->b = new B(); // PHP 5 only $a2 = clone $a1; dump($a1); dump($a2);
출력 결과는 다음과 같습니다.
object(A)#1 (2) { ["a"]=> int(123) ["b"]=> object(B)#2 (1) { ["d"]=> NULL } } object(A)#3 (2) { ["a"]=> int(123) ["b"]=> object(B)#2 (1) { ["d"]=> NULL } }
보시다시피 $a1과 $a2는 분명히 서로 다른 두 객체입니다(객체 식별자가 다릅니다). 그러나 한 가지 주목해야 할 점은 "b"가 가리키는 개체 식별자가 모두 #2라는 것입니다. 이는 두 개체가 동일하다는 것을 증명합니다. 이는 "얕은 복사본"의 "결함"입니다. 그러나 때로는 이 두 개체가 필요합니다. 동일하므로 PHP의 복제본은 기본적으로 "얕은 복사본"으로 설정됩니다.
왜 얕은 카피라고 부르나요?
복사할 때 모든 속성은 "값으로 전달"되고, 위의 b 속성은 객체 식별자를 저장하므로 "참조로 전달"과 동일하기 때문에 이는 완전한 복사본이 아니므로 "얕은"이라고 합니다. 복사".
딥 카피
위에서 언급한 것처럼 clone 키워드를 사용하면 이전 객체의 __clone() 메서드가 자동으로 호출되고(그러면 복사된 객체가 반환됨) __clone() 메서드만 다시 작성하면 됩니다. 반환된 객체의 "참조에 의한 전달" 속성이 다른 새 객체를 가리키도록 해당 클래스입니다. 다음은 예입니다. 실제로 __clone()을 다시 작성하려면 더 많은 단계가 필요한 "얕은 복사본"의 예를 비교할 수 있습니다.
<?php function dump($var){ var_dump($var); echo "<br/>"; } class B{ public $d; } class A{ public $a; public $b; public function d(){ echo "A -> d"; } public function __clone(){ // clone自己 $this->b = clone $this->b; } } $a1 = new A(); $a1->a = 123; // 这里对象属性的值是一个对象示例,其实就是存储了对象标识符。使用clone关键字生成的拷贝中的b属性仍然指向旧对象的b属性指向的对象,这是"浅拷贝"出现的问题。如果需要指向一个新的对象,必须"深拷贝" $a1->b = new B(); // PHP 5 only $a2 = clone $a1; dump($a1); dump($a2);
결과가 다릅니다. b 속성의 객체 식별자에 주의하세요.
object(A)#1 (2) { ["a"]=> int(123) ["b"]=> object(B)#2 (1) { ["d"]=> NULL } } object(A)#3 (2) { ["a"]=> int(123) ["b"]=> object(B)#4 (1) { ["d"]=> NULL } }