Menu
CoddyTech

Triển khai trait

Thuộc phần Lập trình hướng đối tượng trong hành trình Rust của Coddy. Bài học 30 trên 61.

Bây giờ bạn đã biết cách định nghĩa một trait, hãy cùng xem cách để một struct đáp ứng hợp đồng đó. Việc triển khai trait kết nối yêu cầu trừu tượng với hành vi cụ thể.

Cú pháp sử dụng impl TraitName for StructName:

trait Speak {
    fn speak(&self) -> String;
}

struct Dog {
    name: String,
}

impl Speak for Dog {
    fn speak(&self) -> String {
        format!("{} says: Woof!", self.name)
    }
}

Khối impl Speak for Dog cho Rust biết rằng Dog đang triển khai trait Speak. Bên trong, bạn viết phần thân phương thức thực tế. Đây là nơi bạn định nghĩa chó nói như thế nào.

Sức mạnh của các trait sẽ trở nên rõ ràng khi nhiều kiểu cùng triển khai một trait:

struct Cat {
    name: String,
}

impl Speak for Cat {
    fn speak(&self) -> String {
        format!("{} says: Meow!", self.name)
    }
}

Cả Dog và Cat giờ đều có khả năng Speak, nhưng mỗi kiểu lại có cách triển khai riêng. Bạn có thể gọi .speak() trên một trong hai kiểu:

let dog = Dog { name: String::from("Rex") };
let cat = Cat { name: String::from("Whiskers") };

println!("{}", dog.speak());  // Rex kêu: Woof!
println!("{}", cat.speak());  // Whiskers kêu: Meow!

Đây là nền tảng của tính đa hình trong Rust: các kiểu dữ liệu khác nhau, cùng một giao diện, hành vi riêng biệt.

challenge icon

Thử thách

Dễ

Hãy làm cho trait trở nên hữu ích bằng cách triển khai chúng cho các kiểu khác nhau! Bạn sẽ tạo một trait Describable và triển khai trait này cho hai struct khác nhau, mỗi struct cung cấp một mô tả riêng.

Bạn sẽ sắp xếp code trong ba tệp:

  • describable.rs: Định nghĩa một trait công khai Describable với phương thức describe(&self) -> String.
  • items.rs: Tạo hai struct công khai triển khai trait của bạn:
    • Book có trường title công khai (String)
    • Movie có trường name công khai (String)
    Mỗi struct cần triển khai Describable với định dạng mô tả riêng.
  • main.rs: Kết hợp các module, tạo instance của cả hai struct, rồi gọi phương thức describe để cho thấy cùng một trait tạo ra đầu ra khác nhau cho các kiểu khác nhau.

Book cần tự mô tả là Book: {title} và Movie cần tự mô tả là Film: {name}. Hãy chú ý cách mỗi kiểu đáp ứng cùng một giao ước nhưng có hành vi riêng!

Trong tệp chính, hãy tạo một cuốn sách và một bộ phim bằng hai đầu vào đã cho, sau đó in mô tả của chúng trên các dòng riêng biệt.

Đầu ra của bạn cần theo định dạng này:

Book: {title}
Film: {name}

Ví dụ, với đầu vào 1984 và Inception:

Book: 1984
Film: Inception

Bạn sẽ nhận hai đầu vào: tên sách và tên phim.

Tự làm thử

mod describable;
mod items;

use describable::Describable;
use items::{Book, Movie};

fn main() {
    // Đọc dữ liệu đầu vào
    let mut title = String::new();
    std::io::stdin().read_line(&mut title).expect("Failed to read line");
    let title = title.trim().to_string();
    
    let mut name = String::new();
    std::io::stdin().read_line(&mut name).expect("Failed to read line");
    let name = name.trim().to_string();
    
    // TODO: Tạo một instance Book với title
    
    // TODO: Tạo một instance Movie với name
    
    // TODO: In ra mô tả của cuốn sách
    
    // TODO: In ra mô tả của bộ phim
}
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch Rust online