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, otomatik | Basit, sadece yığın (stack) verisi |
Clone | .clone() aracılığıyla açık | Kopyalanabilir 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.
Görev
KolayCopy 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— genelxveyalanlarına sahip (her ikisi dei32). Yalnızca ilkel türler içerdiği için hemCopyhem deClonetüretin, böylece atama yapıldığında örtük olarak kopyalanabilir.NamedLocation— genelname(String) vex/yalanlarına sahip (i32). BirStringiçerdiği için yalnızcaClonetüretebilirsiniz —Copydeğ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
GridPointbaş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
- Bir
Çı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, otomatik | Basit, 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})"
}
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
1Metotlar ve Davranış
Uygulama Bloklarına GirişSelf ParametresiDeğiştirilebilir Metotlarİlişkili FonksiyonlarBirden Fazla Uygulama BloğuMetot ZincirlemeÖzet - Dikdörtgen Eylemleri4Proje: Sanal Evcil Hayvan
Evcil Hayvanı TanımlamaEvcil Hayvanı Besleme7Standart Trait'ler
Debug Trait'iDisplay Trait'iClone ve CopyEşitlik Trait'leriÖzet - Yazdırılabilir Nokta2Kapsülleme ve Modüller
Modül TemelleriPublic Anahtar KelimesiPrivate AlanlarGetter'larSetter'larÖzet - Güvenli Kasa5Generic Yapılar
Generic Struct'larGeneric MetotlarÇoklu Generic TürlerGeneric FonksiyonlarÖzet - Koordinat Noktası8Sınırlandırıcı Olarak Trait'ler
Trait Sınırlandırıcı SözdizimiÇoklu SınırlandırıcılarWhere CümleciğiTrait'ler ile Tip DöndürmeÖzet - Generic Yazıcı11Rust'ta Tasarım Kalıpları
Newtype KalıbıKompozisyonDrop Trait'iFrom ve IntoÖzet - Smart Pointer Mock3İleri Seviye Enum'lar
Veri İçeren Enum'larEnum MetotlarıVeri Varyantlarını EşlemeOption Enum'ına Yeniden BakışÖzet - Shape Enum6Trait Tanımlama
Trait Nedir?Traitleri UygulamaVarsayılan UygulamalarVarsayılanları Geçersiz KılmaParametreli TraitlerÖzet - Media Player