Menu
Coddy logo textTech

Nesne Klonlama: Derinlemesine İnceleme

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

Bu kursun başlarında __clone sihirli metodu hakkında bilgi edindiniz. Şimdi, nesneler özellik olarak başka nesneler içerdiğinde yüzeysel (shallow) ve derin (deep) kopyalama arasındaki kritik farkı inceleyelim.

Varsayılan olarak PHP, kopyalama işlemi sırasında sığ bir kopyalama (shallow copy) gerçekleştirir. Skaler değerler çoğaltılır, ancak nesne özellikleri aynı nesnelere referans olarak kalmaya devam eder:

<?php
class Address {
    public function __construct(public string $city) {}
}

class Person {
    public function __construct(
        public string $name,
        public Address $address
    ) {}
}

$original = new Person("Alice", new Address("Paris"));
$clone = clone $original;

$clone->name = "Bob";
$clone->address->city = "London";

echo $original->name . " - " . $original->address->city;

Çıktı:

Alice - London

$clone->name değerini değiştirmenin orijinali etkilemediğini, ancak adres şehrini değiştirmenin etkilediğini fark edin! Her iki nesne de aynı Address örneğini paylaşıyor.

İç içe geçmiş nesnelerin de kopyalandığı bir derin kopya oluşturmak için __clone metodunu uygulayın:

<?php
class Person {
    public function __construct(
        public string $name,
        public Address $address
    ) {}
    
    public function __clone(): void {
        $this->address = clone $this->address;
    }
}

$original = new Person("Alice", new Address("Paris"));
$clone = clone $original;
$clone->address->city = "London";

echo $original->address->city;

Çıktı:

Paris

Artık her Person kendi bağımsız Address nesnesine sahip. Nesneleriniz birden fazla iç içe geçmiş nesne içerdiğinde, orijinal ile kopya arasında gerçek bağımsızlık sağlamak için __clone içinde her birini kopyalamanız gerekir.

challenge icon

Görev

Kolay

Yüzeysel (shallow) ve derin (deep) kopyalama arasındaki farkı gösteren bir belge yönetim sistemi oluşturalım. Yazar bilgilerini içeren belgeler oluşturacak ve bir belgeyi kopyalamanın gerçekten bağımsız bir kopya oluşturmasını sağlayacaksınız.

Kodunuzu üç dosya halinde düzenleyeceksiniz:

  • Author.php — Bir belgenin yazarını temsil eden bir Author sınıfı oluşturun. Genel bir $name (string) ve genel bir $email (string) tanımlamak için constructor promotion kullanın.
  • Document.php — Bir yazar içeren bir Document sınıfı oluşturun. Author dosyasını dahil edin. Sınıf şunları yapmalıdır:
    • Genel bir $title (string) ve genel bir $author (Author) için constructor promotion kullanın
    • Derin kopyalama gerçekleştirmek için __clone() sihirli metodunu uygulayın — bir belge kopyalandığında, kopyanın yazarında yapılan değişikliklerin orijinali etkilememesi için yazarı da kopyalanmalıdır
    • "[title] by [author name] ([author email])" döndüren bir getInfo() metoduna sahip olun
  • main.php — Document dosyasını dahil edin. Üç girdi alacaksınız: bir belge başlığı, bir yazar adı ve bir yazar e-postası.

    Sağlanan girdileri kullanarak bir Author ile bir Document oluşturun. Belgeyi kopyalayın, ardından kopyanın yazar adına " (Copy)" ekleyerek ve kopyanın başlığının başına "Copy of " ekleyerek kopyayı değiştirin.

    İki satır yazdırın:

    • Orijinal belgenin bilgileri
    • Kopyalanan belgenin bilgileri

    Derin kopyalamanız doğru şekilde uygulandıysa, kopyanın yazarı değiştirildikten sonra bile orijinal belgenin yazarı değişmeden kalmalıdır.

Bu meydan okuma, derin kopyalamanın neden önemli olduğunu gösterir — __clone() metodunun uygun şekilde uygulanması olmadan, her iki belge de aynı Author nesnesini paylaşır ve birini değiştirmek diğerini de etkiler.

Kopya kağıdı

Varsayılan olarak PHP, nesneleri kopyalarken bir yüzeysel kopyalama (shallow copy) gerçekleştirir. Skaler değerler çoğaltılır, ancak nesne özellikleri aynı nesnelere referans olarak kalmaya devam eder.

Yüzeysel kopyalama örneği:

<?php
class Address {
    public function __construct(public string $city) {}
}

class Person {
    public function __construct(
        public string $name,
        public Address $address
    ) {}
}

$original = new Person("Alice", new Address("Paris"));
$clone = clone $original;

$clone->name = "Bob";
$clone->address->city = "London";

echo $original->name . " - " . $original->address->city;
// Çıktı: Alice - London

$clone->name değerini değiştirmek orijinali etkilemez, ancak iç içe geçmiş address nesnesini değiştirmek etkiler; çünkü her iki nesne de aynı Address örneğini paylaşır.

İç içe geçmiş nesnelerin de kopyalandığı bir derin kopyalama (deep copy) oluşturmak için __clone sihirli metodunu uygulayın:

<?php
class Person {
    public function __construct(
        public string $name,
        public Address $address
    ) {}
    
    public function __clone(): void {
        $this->address = clone $this->address;
    }
}

$original = new Person("Alice", new Address("Paris"));
$clone = clone $original;
$clone->address->city = "London";

echo $original->address->city;
// Çıktı: Paris

Nesneler birden fazla iç içe geçmiş nesne içerdiğinde, orijinal ile kopya arasında gerçek bir bağımsızlık sağlamak için __clone içinde her birini kopyalamanız gerekir.

Kendin dene

<?php

require_once 'Document.php';

// Girdileri oku
$title = trim(fgets(STDIN));
$authorName = trim(fgets(STDIN));
$authorEmail = trim(fgets(STDIN));

// TODO: Sağlanan isim ve e-posta ile bir Yazar (Author) oluşturun

// TODO: Sağlanan başlık ve Yazar ile bir Belge (Document) oluşturun

// TODO: Belgeyi kopyalayın (clone)

// TODO: Kopya belgenin yazar isminin sonuna " (Copy)" ekleyerek değiştirin

// TODO: Kopya belgenin başlığının başına "Copy of " ekleyerek değiştirin

// TODO: Orijinal belgenin bilgilerini yazdırın

// TODO: Kopyalanan belgenin bilgilerini yazdırın

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