Menu
Coddy logo textTech

Clone ve Copy

Coddy'nin Rust Journey'sinin Object Oriented Programming bölümünün bir parçası — ders 37 / 61.

Rust'ta, bir değeri başka bir değişkene atadığınızda, sahiplik genellikle taşınır—orijinal değişken geçersiz hale gelir. Ancak, iki standart trait bu davranışı değiştirir: Clone ve Copy.

Copy özelliği örtük bitsel kopyalamayı sağlar. Bir tür Copy özelliğini uyguladığında, onu başka bir değişkene atamak sahipliği taşımak yerine otomatik bir kopya oluşturur:

#[derive(Copy, Clone)]
struct Point {
    x: i32,
    y: i32,
}

let p1 = Point { x: 10, y: 20 };
let p2 = p1;  // p1 kopyalandı, taşınmadı

println!("{}, {}", p1.x, p2.x);  // Her ikisi de geçerli!

Clone trait'i, .clone() metodu aracılığıyla açık derin kopyalama sağlar. Copy türettiğiniz her durumda gereklidir, ancak açık kopyalamaya ihtiyaç duyan türler için tek başına da kullanılabilir:

let p3 = p1.clone();  // Açık kopyalama

Önemli bir kısıtlama vardır: Copy, yalnızca tüm alanların da Copy uyguladığı türler için türetilebilir. Tam sayılar ve ondalıklı sayılar gibi basit türler Copy özelliğine sahiptir, ancak String değildir—yığın (heap) belleğini yönetir. Eğer struct'ınız bir String içeriyorsa, Copy değil, yalnızca Clone türetebilirsiniz.

Özellik (Trait)DavranışKullanım
CopyÖrtük, otomatikBasit, sadece yığın (stack) verisi
Clone.clone() aracılığıyla açıkKopyalanabilir herhangi bir veri

İlkel alanlara sahip basit struct'lar için, her iki trait'i de türetmek, sahiplik (ownership) konusunda endişelenmeden değerleri özgürce atamanıza olanak tanır.

challenge icon

Görev

Kolay

Copy ve Clone trait'leri arasındaki farkı gösteren bir koordinat sistemi inşa edelim! Rust'ın türettiğiniz trait'lere bağlı olarak çoğaltma işlemini nasıl farklı şekilde ele aldığını görmek için iki struct oluşturacaksınız; biri örtük olarak kopyalanabilen, diğeri ise açıkça klonlama gerektiren.

Kodunuzu iki dosya halinde düzenleyeceksiniz:

  • coordinates.rs: Farklı koordinat türlerini temsil eden iki genel (public) struct tanımlayın:
    • GridPoint — genel x ve y alanlarına sahip (her ikisi de i32). Yalnızca ilkel türler içerdiği için hem Copy hem de Clone türetin, böylece atama yapıldığında örtük olarak kopyalanabilir.
    • NamedLocation — genel name (String) ve x/y alanlarına sahip (i32). Bir String içerdiği için yalnızca Clone türetebilirsiniz — Copy değil. Bu struct, çoğaltmak için açıkça .clone() çağrıları gerektirecektir.
  • main.rs: Koordinat modülünüzü dahil edin ve her bir struct'ın çoğaltıldığında nasıl farklı davrandığını gösterin. Sağlanan girdileri kullanarak örnekler oluşturun, ardından şunları gösterin:
    • Bir GridPoint başka bir değişkene atanabilir ve her ikisi de geçerli kalır (örtük kopya)
    • Bir NamedLocation, orijinali geçerli tutarken bir kopya oluşturmak için .clone() kullanmalıdır

Çıktınız, çoğaltmadan sonra her iki değişkenin de geçerli olduğunu kanıtlamak için hem orijinal hem de kopyalanmış/klonlanmış değerleri göstermelidir:

Original point: ({x}, {y})
Copied point: ({x}, {y})
Original location: {name} at ({x}, {y})
Cloned location: {name} at ({x}, {y})

Örneğin, 5, 10 ve Home girdileriyle:

Original point: (5, 10)
Copied point: (5, 10)
Original location: Home at (5, 10)
Cloned location: Home at (5, 10)

Üç girdi alacaksınız: x koordinatı (i32 olarak ayrıştırın), y koordinatı (i32 olarak ayrıştırın) ve konum adı.

Kopya kağıdı

Copy özelliği, örtük bit düzeyinde kopyalamayı (implicit bitwise copying) etkinleştirir. Bir tür Copy özelliğini uyguladığında, onu başka bir değişkene atamak, sahipliği taşımak (move) yerine otomatik bir kopya oluşturur:

#[derive(Copy, Clone)]
struct Point {
    x: i32,
    y: i32,
}

let p1 = Point { x: 10, y: 20 };
let p2 = p1;  // p1 kopyalandı, taşınmadı

println!("{}, {}", p1.x, p2.x);  // Her ikisi de geçerlidir!

Clone özelliği, .clone() metodu aracılığıyla açık derin kopyalama (explicit deep copying) sağlar:

let p3 = p1.clone();  // Açık kopyalama

Copy, yalnızca tüm alanları da Copy özelliğini uygulayan türler için türetilebilir. Tam sayılar ve ondalıklı sayılar gibi basit türler Copy özelliğine sahiptir, ancak String sahip değildir. Eğer yapınız (struct) bir String içeriyorsa, Copy değil, yalnızca Clone türetebilirsiniz.

Özellik (Trait)DavranışKullanım
CopyÖrtük, otomatikBasit, yalnızca yığın (stack) verileri
Clone.clone() ile açıkÇoğaltılabilir her türlü veri

Copy türetirken, aynı zamanda Clone da türetmeniz gerekir.

Kendin dene

mod coordinates;

use coordinates::{GridPoint, NamedLocation};

fn main() {
    // Girdileri oku
    let mut input1 = String::new();
    std::io::stdin().read_line(&mut input1).expect("Failed to read line");
    let x: i32 = input1.trim().parse().expect("Invalid number");

    let mut input2 = String::new();
    std::io::stdin().read_line(&mut input2).expect("Failed to read line");
    let y: i32 = input2.trim().parse().expect("Invalid number");

    let mut input3 = String::new();
    std::io::stdin().read_line(&mut input3).expect("Failed to read line");
    let name = input3.trim().to_string();

    // TODO: x ve y ile bir GridPoint örneği oluşturun

    // TODO: Başka bir değişkene atayarak örtük kopyalamayı (implicit copy) gösterin
    // (GridPoint, Copy özelliğini uygular, bu nedenle otomatik olarak bir kopya oluşturur)

    // TODO: Orijinal ve kopyalanan noktayı yazdırın
    // Format: "Original point: ({x}, {y})"
    // Format: "Copied point: ({x}, {y})"

    // TODO: name, x ve y ile bir NamedLocation örneği oluşturun

    // TODO: Açık kopyalamayı (explicit clone) gösterin (NamedLocation sadece Clone özelliğini uygular, Copy özelliğini değil)
    // Bir kopya oluşturmak için .clone() kullanın

    // TODO: Orijinal ve klonlanan konumu yazdırın
    // Format: "Original location: {name} at ({x}, {y})"
    // Format: "Cloned location: {name} at ({x}, {y})"
}
quiz iconKendini test et

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

Object Oriented Programming bölümündeki tüm dersler