Menu
Coddy logo textTech

__clone & Nesne Klonlama

Coddy'nin PHP Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 48 / 91.

PHP'de bir nesneyi başka bir değişkene atadığınızda, bir kopya oluşturmazsınız - her iki değişken de aynı nesneye işaret eder. Gerçekten bağımsız bir kopya oluşturmak için clone anahtar kelimesini kullanmanız gerekir:

<?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;

Çıktı:

999.99 - 899.99

Varsayılan olarak, PHP bir yüzeysel kopyalama (shallow copy) gerçekleştirir - tüm özellik değerlerini doğrudan kopyalar. Bu, skaler değerler için sorunsuz çalışır, ancak nesnenizin içindeki nesneler hala aynı örneğe başvurmaya devam eder. __clone() sihirli yöntemi bu davranışı özelleştirmenize olanak tanır:

<?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;

Çıktı:

Original: 101, Clone: 0

__clone() metodu, yüzeysel kopya oluşturulduktan sonra yeni nesne üzerinde çağrılır. Burası; ID'leri sıfırladığınız, iç içe geçmiş nesnelerin yeni kopyalarını oluşturduğunuz veya klonun tamamen bağımsız olması için gereken her türlü temizliği yaptığınız yerdir.

challenge icon

Görev

Kolay

Klonlamanın nasıl bağımsız kopyalar oluşturduğunu ve __clone() sihirli metodunun bir nesne klonlandığında ne olacağını özelleştirmenize nasıl olanak tanıdığını gösteren bir belge sürümleme sistemi oluşturalım.

Kodunuzu iki dosya halinde düzenleyeceksiniz:

  • Document.php — Sürümlenmiş bir belgeyi temsil eden bir Document sınıfı oluşturun. Genel bir $title (string), genel bir $content (string) ve genel bir $version (tamsayı, varsayılan değeri 1) tanımlamak için constructor promotion kullanın. Mevcut zaman damgasını saklayan özel bir $createdAt özelliği ekleyin (yapıcıda date('Y-m-d H:i:s') kullanın). Belgenizin şunlara ihtiyacı vardır:
    • getCreatedAt() — oluşturulma zaman damgasını döndürür
    • __clone() — bir belge klonlandığında, sürüm 1 artmalı ve $createdAt mevcut zaman damgasına sıfırlanmalıdır (klon, "şimdi" oluşturulan yeni bir sürümdür)
  • main.php — Document dosyasını dahil edin. Üç girdi alacaksınız: bir başlık, içerik ve klonlanmış sürüm için yeni bir içerik dizesi. Başlık ve içerikle bir Document oluşturun. Ardından yeni bir sürüm oluşturmak için onu klonlayın ve klonun içeriğini yeni içerik dizesiyle güncelleyin. Dört satır yazdırın:
    • Orijinal belgenin sürümü
    • Klonlanmış belgenin sürümü
    • Orijinal belgenin içeriği
    • Klonlanmış belgenin içeriği

Bu sistem, __clone() metodunun klonlama sırasında ne olacağını kontrol etmenize nasıl izin verdiğini gösterir. Orijinal belge kendi sürümünü ve oluşturulma zamanını korurken, klon otomatik olarak yeni bir zaman damgasına sahip yeni bir sürüm haline gelir; bu, her klonun yeni bir revizyonu temsil ettiği belge geçmişini izlemek için mükemmeldir.

Kopya kağıdı

Bir nesnenin bağımsız bir kopyasını oluşturmak için clone anahtar kelimesini kullanın:

<?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;
// Çıktı: 999.99 - 899.99

Varsayılan olarak PHP, tüm özellik değerlerinin yüzeysel bir kopyasını (shallow copy) gerçekleştirir. Klonlama davranışını özelleştirmek için __clone() sihirli metodunu kullanın:

<?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;
// Çıktı: Original: 101, Clone: 0

__clone() metodu, yüzeysel kopya oluşturulduktan sonra yeni nesne üzerinde çağrılır; bu da özellikleri sıfırlamanıza veya iç içe geçmiş nesnelerin bağımsız kopyalarını oluşturmanıza olanak tanır.

Kendin dene

<?php

require_once 'Document.php';

// Girdileri oku
$title = trim(fgets(STDIN));
$content = trim(fgets(STDIN));
$newContent = trim(fgets(STDIN));

// TODO: Başlık ve içerik ile bir Document oluşturun

// TODO: Yeni bir sürüm oluşturmak için belgeyi kopyalayın (clone)

// TODO: Kopya belgenin içeriğini yeni içerik dizesiyle güncelleyin

// TODO: Dört satır yazdırın:
// 1. Orijinal belgenin sürümü
// 2. Kopyalanan belgenin sürümü
// 3. Orijinal belgenin içeriği
// 4. Kopyalanan belgenin içeriği

?>
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler