Traits di Rust — Rust

Traits di Rust Trait adalah cara mendefinisikan perilaku bersama yang bisa diimplementasikan oleh berbagai tipe — mirip interface di Java atau protocol di…

Traits di Rust

Trait adalah cara mendefinisikan perilaku bersama yang bisa diimplementasikan oleh berbagai tipe — mirip interface di Java atau protocol di Swift, tapi dengan kemampuan lebih.

Mendefinisikan Trait

trait Ringkas {
    fn ringkasan(&self) -> String;
}

Trait ini berkata: "tipe apa pun yang mengimplementasikan Ringkas harus punya method ringkasan yang return String".

Implementasi Trait untuk Tipe

struct Artikel {
    judul: String,
    penulis: String,
    isi: String,
}

impl Ringkas for Artikel {
    fn ringkasan(&self) -> String {
        format!("{}, oleh {}", self.judul, self.penulis)
    }
}

struct Tweet {
    user: String,
    konten: String,
}

impl Ringkas for Tweet {
    fn ringkasan(&self) -> String {
        format!("@{}: {}", self.user, self.konten)
    }
}

Default Method Implementation

Trait bisa menyediakan implementasi default — tipe yang meng-implement bisa memilih memakai default atau override:

trait Sapa {
    fn nama(&self) -> String;

    // Default implementation
    fn halo(&self) -> String {
        format!("Halo, {}!", self.nama())
    }
}

struct Orang { nama: String }

impl Sapa for Orang {
    fn nama(&self) -> String {
        self.nama.clone()
    }
    // halo() pakai default
}

Trait sebagai Parameter

fn umumkan(item: &impl Ringkas) {
    println!("BARU: {}", item.ringkasan());
}

// Bentuk panjangnya pakai generic + trait bound
fn umumkan_v2<T: Ringkas>(item: &T) {
    println!("BARU: {}", item.ringkasan());
}

Multiple Trait Bounds

use std::fmt::Display;

fn tampilkan<T: Display + Clone>(item: T) {
    let copy = item.clone();
    println!("{} {}", item, copy);
}

Standard Traits dengan derive

Beberapa trait penting dari standard library bisa di-derive otomatis:

#[derive(Debug, Clone, PartialEq)]
struct Produk {
    nama: String,
    harga: f64,
}

let p1 = Produk { nama: "Buku".into(), harga: 50000.0 };
let p2 = p1.clone();          // dari Clone
println!("{:?}", p1);         // dari Debug
println!("{}", p1 == p2);     // dari PartialEq

Trait Objects — Polymorphism Dinamis

Jika butuh menyimpan berbagai tipe yang implement trait yang sama dalam satu koleksi, pakai &dyn Trait atau Box<dyn Trait>:

let items: Vec<Box<dyn Ringkas>> = vec![
    Box::new(Artikel { /* .. */ }),
    Box::new(Tweet { /* .. */ }),
];

for item in &items {
    println!("{}", item.ringkasan());
}

Trade-off: dyn Trait pakai dynamic dispatch (sedikit lebih lambat). Generic pakai static dispatch (cepat, tapi binary lebih besar).

Yang akan kamu pelajari