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

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

Sep 01, 2016 am 12:00 AM

참고링크:

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으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)