__clone 및 객체 복제
Coddy PHP 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 91개 중 48번째.
PHP에서 한 객체를 다른 변수에 할당할 때, 복사본이 생성되지 않으며 두 변수 모두 동일한 객체를 가리킵니다. 실제 독립적인 복사본을 만들려면 clone 키워드를 사용해야 합니다:
<?php
class Product {
public function __construct(
public string $name,
public float $price
) {}
}
$original = new Product("Laptop", 999.99);
$copy = clone $original;
$copy->price = 899.99;
echo $original->price . " - " . $copy->price;
출력:
999.99 - 899.99기본적으로 PHP는 얕은 복사(shallow copy)를 수행합니다. 즉, 모든 속성 값을 직접 복사합니다. 이는 스칼라 값에는 잘 작동하지만, 객체 내부의 객체들은 여전히 동일한 인스턴스를 참조합니다. __clone() 매직 메서드를 사용하면 이 동작을 사용자 정의할 수 있습니다:
<?php
class Order {
public function __construct(
public int $id,
public array $items = []
) {}
public function __clone(): void {
$this->id = 0;
$this->items = [];
}
}
$order1 = new Order(101, ["Book", "Pen"]);
$order2 = clone $order1;
echo "Original: " . $order1->id . ", Clone: " . $order2->id;
출력:
Original: 101, Clone: 0__clone() 메서드는 얕은 복사(shallow copy)가 수행된 후 새 객체에서 호출됩니다. 이 메서드 내에서 ID를 재설정하거나, 중첩된 객체의 새 복사본을 생성하거나, 복제본이 완전히 독립적이 되도록 하는 데 필요한 정리 작업을 수행합니다.
챌린지
쉬움클로닝이 어떻게 독립적인 복사본을 생성하는지, 그리고 __clone() 매직 메서드를 통해 객체가 클론될 때 어떤 일이 일어나는지 어떻게 커스터마이징할 수 있는지 보여주는 문서 버전 관리 시스템을 만들어 보겠습니다.
코드는 두 개의 파일로 구성됩니다:
Document.php— 버전이 지정된 문서를 나타내는Document클래스를 생성합니다. 생성자 프로모션(constructor promotion)을 사용하여 public$title(string), public$content(string), 그리고 public$version(integer, 기본값 1)을 정의하세요. 현재 타임스탬프를 저장하는 private$createdAt속성을 추가하세요 (생성자에서date('Y-m-d H:i:s')를 사용하세요). 문서에 필요한 요소:getCreatedAt()— 생성 타임스탬프를 반환합니다.__clone()— 문서가 클론될 때, version은 1씩 증가해야 하며,$createdAt은 현재 타임스탬프로 재설정되어야 합니다 (클론은 "지금" 생성된 새로운 버전입니다).
main.php— Document 파일을 포함합니다. 세 가지 입력을 받게 됩니다: 제목(title), 내용(content), 그리고 클론된 버전에 사용할 새로운 내용 문자열(new content string). 제목과 내용을 사용하여Document를 생성하세요. 그런 다음 이를 클론하여 새 버전을 만들고, 클론의 내용을 새로운 내용 문자열로 업데이트하세요. 다음 네 줄을 출력하세요:- 원본 문서의 버전
- 클론된 문서의 버전
- 원본 문서의 내용
- 클론된 문서의 내용
이 시스템은 __clone()을 통해 클로닝 과정에서 일어나는 일을 어떻게 제어할 수 있는지 보여줍니다. 원본 문서는 자신의 버전과 생성 시간을 유지하는 반면, 클론은 자동으로 새로운 타임스탬프를 가진 새 버전이 됩니다. 이는 각 클론이 새로운 개정판을 나타내는 문서 이력 추적에 적합합니다.
치트 시트
객체의 독립적인 복사본을 생성하려면 clone 키워드를 사용하세요:
<?php
class Product {
public function __construct(
public string $name,
public float $price
) {}
}
$original = new Product("Laptop", 999.99);
$copy = clone $original;
$copy->price = 899.99;
echo $original->price . " - " . $copy->price;
// 출력: 999.99 - 899.99
기본적으로 PHP는 모든 속성 값에 대해 얕은 복사(shallow copy)를 수행합니다. 클로닝 동작을 사용자 정의하려면 __clone() 매직 메서드를 사용하세요:
<?php
class Order {
public function __construct(
public int $id,
public array $items = []
) {}
public function __clone(): void {
$this->id = 0;
$this->items = [];
}
}
$order1 = new Order(101, ["Book", "Pen"]);
$order2 = clone $order1;
echo "Original: " . $order1->id . ", Clone: " . $order2->id;
// 출력: Original: 101, Clone: 0
__clone() 메서드는 얕은 복사가 이루어진 후 새 객체에서 호출되며, 이를 통해 속성을 초기화하거나 중첩된 객체의 독립적인 복사본을 생성할 수 있습니다.
직접 해보기
<?php
require_once 'Document.php';
// 입력 읽기
$title = trim(fgets(STDIN));
$content = trim(fgets(STDIN));
$newContent = trim(fgets(STDIN));
// TODO: 제목과 내용을 사용하여 Document 객체 생성
// TODO: 문서를 복제하여 새 버전 생성
// TODO: 복제본의 내용을 새 내용 문자열로 업데이트
// TODO: 다음 네 줄을 출력:
// 1. 원본 문서의 버전
// 2. 복제된 문서의 버전
// 3. 원본 문서의 내용
// 4. 복제된 문서의 내용
?>이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
8매직 메서드
매직 메서드 소개__toString 및 __debugInfo__get, __set, __isset, __unset__call 및 __callStatic__clone 및 객체 복제__serialize 및 __unserialize요약 - 커스텀 컬렉션