Clone dan Copy
Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan Rust di Coddy. Pelajaran 37 dari 61.
Di Rust, saat kamu menetapkan nilai ke variabel lain, ownership biasanya berpindah: variabel asal menjadi tidak valid. Namun, dua trait standar mengubah perilaku ini: Clone dan Copy.
Trait Copy memungkinkan penyalinan bitwise secara implisit. Saat suatu tipe mengimplementasikan Copy, menetapkannya ke variabel lain akan membuat salinan otomatis alih-alih memindahkan kepemilikan:
#[derive(Copy, Clone)]
struct Point {
x: i32,
y: i32,
}
let p1 = Point { x: 10, y: 20 };
let p2 = p1; // p1 disalin, bukan dipindahkan
println!("{}, {}", p1.x, p2.x); // Keduanya masih valid!
Trait Clone menyediakan penyalinan mendalam secara eksplisit melalui method .clone(). Trait ini wajib digunakan setiap kali kamu menurunkan Copy, tetapi juga dapat digunakan sendiri untuk tipe yang memerlukan penyalinan eksplisit:
let p3 = p1.clone(); // Salinan eksplisit
Ada batasan penting: Copy hanya dapat diturunkan untuk tipe yang semua field-nya juga mengimplementasikan Copy. Tipe sederhana seperti bilangan bulat dan bilangan pecahan mengimplementasikan Copy, tetapi String tidak. String mengelola memori heap. Jika struct-mu berisi String, kamu hanya dapat menurunkan Clone, bukan Copy.
| Sifat | Perilaku | Penggunaan |
|---|---|---|
Copy | Implisit, otomatis | Data sederhana yang hanya berada di stack |
Clone | Eksplisit melalui .clone() | Data apa pun yang dapat diduplikasi |
Untuk struct sederhana dengan field primitif, menurunkan kedua trait memungkinkan kamu menetapkan nilai dengan bebas tanpa perlu mengkhawatirkan ownership.
Tantangan
MudahMari kita buat sistem koordinat yang menunjukkan perbedaan antara trait Copy dan Clone! Kamu akan membuat dua struct, satu yang dapat disalin secara implisit dan satu yang perlu di-clone secara eksplisit, untuk melihat bagaimana Rust menangani duplikasi secara berbeda berdasarkan trait yang kamu turunkan.
Kamu akan menyusun kodemu dalam dua file:
coordinates.rs: Definisikan dua struct publik yang merepresentasikan jenis koordinat yang berbeda:GridPoint: dengan field publikxdany(keduanyai32). Karena struct ini hanya berisi tipe primitif, turunkan traitCopydanCloneagar struct ini dapat disalin secara implisit saat ditetapkan ke variabel.NamedLocation: dengan field publikname(String) serta fieldx/y(i32). Karena struct ini berisiString, kamu hanya dapat menurunkan traitClone, bukanCopy. Struct ini memerlukan pemanggilan.clone()secara eksplisit untuk membuat duplikat.
main.rs: Gunakan module koordinatmu dan tunjukkan bagaimana perilaku setiap struct berbeda saat diduplikasi. Buat instance menggunakan input yang diberikan, lalu tunjukkan bahwa:GridPointdapat ditetapkan ke variabel lain dan keduanya tetap valid (penyalinan implisit)NamedLocationharus menggunakan.clone()untuk membuat duplikat sementara nilai aslinya tetap valid
Output-mu harus menampilkan nilai asli dan nilai yang disalin atau di-clone untuk membuktikan bahwa kedua variabel tetap valid setelah duplikasi:
Original point: ({x}, {y})
Copied point: ({x}, {y})
Original location: {name} at ({x}, {y})
Cloned location: {name} at ({x}, {y})Contohnya, dengan input 5, 10, dan Home:
Original point: (5, 10)
Copied point: (5, 10)
Original location: Home at (5, 10)
Cloned location: Home at (5, 10)Kamu akan menerima tiga input: koordinat x (parse sebagai i32), koordinat y (parse sebagai i32), dan nama lokasi.
Coba sendiri
mod coordinates;
use coordinates::{GridPoint, NamedLocation};
fn main() {
// Baca input
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: Buat instance GridPoint dengan x dan y
// TODO: Tunjukkan penyalinan implisit dengan menetapkan nilainya ke variabel lain
// (GridPoint mengimplementasikan Copy, jadi salinan dibuat secara otomatis)
// TODO: Tampilkan titik asli dan salinannya
// Format: "Original point: ({x}, {y})"
// Format: "Copied point: ({x}, {y})"
// TODO: Buat instance NamedLocation dengan name, x, dan y
// TODO: Tunjukkan kloning eksplisit (NamedLocation hanya mengimplementasikan Clone, bukan Copy)
// Gunakan .clone() untuk membuat duplikat
// TODO: Tampilkan lokasi asli dan hasil kloningnya
// Format: "Original location: {name} at ({x}, {y})"
// Format: "Cloned location: {name} at ({x}, {y})"
}
Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.
Semua pelajaran di Pemrograman Berorientasi Objek
1Method dan Perilaku
Pengantar Blok ImplementasiParameter SelfMethod MutableFungsi TerkaitBeberapa Blok ImplementasiMethod BerantaiRangkuman: Aksi Persegi Panjang4Proyek: Hewan Peliharaan Virtual
Mendefinisikan Hewan PeliharaanMemberi Makan Hewan Peliharaan7Trait Standar
Trait DebugTrait DisplayClone dan CopyTrait KesetaraanRingkasan: Titik yang Dapat Dicetak2Enkapsulasi dan module
Dasar-Dasar moduleKata Kunci publicField privateGetterSetterRekap: Loker AmanLatihan sendiri: Compiler Rust online