Chuyển đến nội dung chính

Bài 5: Traits & Generics

Trait definition, default implementations. Generic types, trait bounds. Associated types, supertraits. impl Trait, dyn Trait. Derive macros. Common traits (Display, Debug, Clone, From/Into).

💻 Lập trình — Bài 5 Bài 5: Traits & Generics

Rust: Từ Cơ bản đến Nâng cao

Phần 2: Advanced Rust

xdev.asia

1. Traits

trait Summary {
    fn summarize_author(&self) -> String;

    // Default implementation
    fn summarize(&self) -> String {
        format!("(Read more from {}...)", self.summarize_author())
    }
}

struct Article {
    title: String,
    author: String,
    content: String,
}

impl Summary for Article {
    fn summarize_author(&self) -> String {
        self.author.clone()
    }

    fn summarize(&self) -> String {
        format!("{} by {}: {}...", self.title, self.author, &self.content[..50])
    }
}

2. Generics & Trait Bounds

// Generic function
fn largest<T: PartialOrd>(list: &[T]) -> &T {
    let mut largest = &list[0];
    for item in &list[1..] {
        if item > largest {
            largest = item;
        }
    }
    largest
}

// Multiple trait bounds
fn print_summary<T: Summary + std::fmt::Display>(item: &T) {
    println!("{}: {}", item, item.summarize());
}

// where clause — dễ đọc hơn
fn complex_function<T, U>(t: &T, u: &U) -> String
where
    T: Summary + Clone,
    U: std::fmt::Display + std::fmt::Debug,
{
    format!("{} - {:?}", t.summarize(), u)
}

// Generic struct
struct Pair<T> {
    first: T,
    second: T,
}

impl<T: std::fmt::Display + PartialOrd> Pair<T> {
    fn larger(&self) -> &T {
        if self.first >= self.second { &self.first } else { &self.second }
    }
}

3. Associated Types & Supertraits

// Associated type — type placeholder trong trait
trait Iterator {
    type Item;
    fn next(&mut self) -> Option<Self::Item>;
}

struct Counter {
    count: u32,
    max: u32,
}

impl Iterator for Counter {
    type Item = u32;

    fn next(&mut self) -> Option<Self::Item> {
        if self.count < self.max {
            self.count += 1;
            Some(self.count)
        } else {
            None
        }
    }
}

// Supertrait — trait kế thừa
trait PrettyPrint: std::fmt::Display {
    fn pretty_print(&self) {
        println!("╔══════════════╗");
        println!("║ {} ║", self);
        println!("╚══════════════╝");
    }
}

4. impl Trait vs dyn Trait

// impl Trait — static dispatch (monomorphization)
fn notify(item: &impl Summary) -> impl std::fmt::Display {
    format!("Breaking: {}", item.summarize())
}

// dyn Trait — dynamic dispatch (trait object)
fn get_formatter(format: &str) -> Box<dyn Summary> {
    match format {
        "article" => Box::new(Article { /* ... */ }),
        "tweet" => Box::new(Tweet { /* ... */ }),
        _ => panic!("Unknown format"),
    }
}

// Common derives
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
struct ProductId(String);

// From/Into
impl From<String> for ProductId {
    fn from(s: String) -> Self {
        ProductId(s)
    }
}

let id: ProductId = "abc".to_string().into();

Bài tiếp theo: Closures, Iterators & Collections.