>  기사  >  php教程  >  [PHP] 객체 복제(복사) 및 __clone() 메서드

[PHP] 객체 복제(복사) 및 __clone() 메서드

WBOY
WBOY원래의
2016-09-01 00:00:451355검색

참고링크:

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

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.