Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Lesson 6 — Traits, Generics, and Abstractions


🎯 Learning Objectives

  • Hiểu traits là gì và cách định nghĩa hành vi chung cho nhiều kiểu.
  • Biết cách dùng generics để viết hàm và struct tổng quát, tránh lặp code.
  • Thực hành xây dựng abstractions để code dễ mở rộng và tái sử dụng.

✅ Explanation & Key Concepts

Traits

Trait = tập hợp method signatures (và có thể default impl). Kiểu nào implement trait thì có thể dùng trait đó.

Generics

Generics cho phép viết hàm/struct với tham số kiểu T, giúp code tổng quát và tái sử dụng.

Abstraction

Traits + generics tạo ra lớp trừu tượng, giúp code dễ mở rộng mà vẫn an toàn kiểu.


💻 Example Implementation

Cargo.toml

[package]
name = "lesson06_traits_generics"
version = "0.1.0"
edition = "2024"

src/main.rs

// Define a trait
trait Summarize {
    fn summary(&self) -> String;
}

// Implement for a struct
struct Article {
    title: String,
    author: String,
}

impl Summarize for Article {
    fn summary(&self) -> String {
        format!("{} by {}", self.title, self.author)
    }
}

// Generic function with trait bound
fn notify<T: Summarize>(item: &T) {
    println!("Notification: {}", item.summary());
}

fn main() {
    let art = Article {
        title: "Async in Rust".to_string(),
        author: "dp".to_string(),
    };

    notify(&art);
}

🛠️ Hands-on Exercises

  1. Basic: Tạo trait Printable với hàm print(&self); implement cho Stringi32.
  2. Intermediate: Viết hàm generic max<T: Ord>(list: &[T]) -> Option<&T> để tìm phần tử lớn nhất.
  3. Challenge: Định nghĩa trait Storage<K,V> với method set/get; implement cho HashMap<K,V>.

🐞 Common Pitfalls & Debugging Tips

Common Pitfalls

  • Quên thêm trait bound (T: Trait) khi dùng method từ trait.
  • Nhầm lẫn giữa impl Trait và generic <T: Trait>.
  • Trait object (Box<dyn Trait>) không giống generics: dùng khi cần dynamic dispatch.

❓ Q&A — Common Questions

Q1. Trait vs Interface (ở ngôn ngữ khác)?

  • Giống nhau ở việc định nghĩa hành vi. Khác ở chỗ trait có default implementation, có thể compose nhiều trait cho cùng một kiểu, và trait bounds mạnh mẽ trong generic functions/structs.

Q2. Khi nào dùng Generics vs Macro vs Trait Object?

  • Generics → monomorphization, an toàn & nhanh, compile-time polymorphism.
  • Macro → sinh code (syntax-level), không phải abstraction runtime.
  • Trait object (dyn Trait) → khi cần chọn hành vi lúc runtime (dynamic dispatch) hoặc cần tính đồng nhất kiểu động trong containers.

Q3. Kết hợp Traits + Generics để tạo API gọn & mạnh?

  • Dùng trait bounds: fn f<T: TraitA + TraitB>(x: T). Tách behavior thành traits nhỏ, cung cấp default impl, và dùng impl Trait trong chữ ký hàm để đơn giản hóa API bên ngoài.

🔄 Migration Notes (Rust 2024+)

Migration Guidance

  • impl Trait ngày càng được ưu tiên vì code gọn.
  • Rust 2024 cải thiện inference trait bound trong một số ngữ cảnh.
  • async fn trong trait đang dần được stable (hiện cần async-trait crate nếu dùng rộng).

📚 References


📖 Glossary of Terms

Key Terms

  • Trait: tập hợp method signatures để chia sẻ hành vi.
  • Generic: tham số hóa kiểu, giúp code tổng quát.
  • Trait bound: ràng buộc yêu cầu một kiểu phải implement trait.
  • Trait object: giá trị động (dyn Trait), hỗ trợ dynamic dispatch.

🌿 Wisdom Note

Đạo Đức Kinh — Chương 11

Tam thập phúc, cộng nhất hồ.

Thirty spokes share the wheel’s hub; it is the center hole that makes it useful.

Traits và generics cũng vậy: chính khoảng trống (abstraction) làm cho code có sức mạnh mở rộng.