Menu
CoddyTech

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.

SifatPerilakuPenggunaan
CopyImplisit, otomatisData sederhana yang hanya berada di stack
CloneEksplisit 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.

challenge icon

Tantangan

Mudah

Mari 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 publik x dan y (keduanya i32). Karena struct ini hanya berisi tipe primitif, turunkan trait Copy dan Clone agar struct ini dapat disalin secara implisit saat ditetapkan ke variabel.
    • NamedLocation: dengan field publik name (String) serta field x/y (i32). Karena struct ini berisi String, kamu hanya dapat menurunkan trait Clone, bukan Copy. 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:
    • GridPoint dapat ditetapkan ke variabel lain dan keduanya tetap valid (penyalinan implisit)
    • NamedLocation harus 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})"
}
quiz iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Pemrograman Berorientasi Objek

Latihan sendiri: Compiler Rust online