Menu
CoddyTech

Phương thức tổng quát

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 25 trên 61.

Một struct generic có thể chứa bất kỳ kiểu nào, nhưng sẽ không hữu ích lắm nếu thiếu các phương thức để thao tác với dữ liệu bên trong. Để định nghĩa phương thức cho struct generic, bạn cần dùng cú pháp đặc biệt trong khối impl.

Điểm mấu chốt là khai báo tham số tổng quát trên chính impl:

struct Wrapper<T> {
    value: T,
}

impl<T> Wrapper<T> {
    fn get(&self) -> &T {
        &self.value
    }
}

Hãy chú ý đến impl<T> đứng trước Wrapper<T>. Điều này cho Rust biết rằng T là tham số kiểu tổng quát (generic type parameter) cho toàn bộ khối triển khai. Nếu không có khai báo này, Rust sẽ tìm một kiểu cụ thể tên là T và không tìm thấy.

Phương thức get trả về &T: một tham chiếu đến bất kỳ kiểu dữ liệu nào mà trình bao bọc chứa. Cách này hoạt động dù T là số nguyên, chuỗi hay bất kỳ kiểu dữ liệu nào khác:

let num_wrapper = Wrapper { value: 100 };
let text_wrapper = Wrapper { value: "Rust" };

println!("{}", num_wrapper.get());  // 100
println!("{}", text_wrapper.get()); // Rust

Cùng một định nghĩa phương thức dùng được cho cả hai, vì kiểu tổng quát (generic) T thích ứng với từng kiểu cụ thể tại thời điểm biên dịch.

challenge icon

Thử thách

Dễ

Hãy mở rộng vùng chứa tổng quát của bạn bằng các phương thức (method)! Bạn sẽ xây dựng một cấu trúc Box (không nhầm với Box tiêu chuẩn của Rust), có thể chứa bất kỳ kiểu dữ liệu nào và cung cấp các phương thức để tương tác với nội dung bên trong.

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

  • mybox.rs: Định nghĩa một cấu trúc tổng quát công khai tên là MyBox<T>, với trường riêng tư contents có kiểu T. Triển khai các phương thức cho cấu trúc này:
    • Một hàm liên kết new tạo một MyBox mới với giá trị đã cho
    • Một phương thức peek trả về tham chiếu đến nội dung bên trong (dùng &self)
    • Một phương thức replace nhận giá trị mới và thay thế nội dung hiện tại (dùng &mut self)
  • main.rs: Đưa module của bạn vào và minh họa cách các phương thức tổng quát hoạt động với những kiểu dữ liệu khác nhau. Bạn sẽ tạo các hộp, xem nội dung bên trong và thay thế giá trị để minh họa cách các phương thức hoạt động.

Hãy nhớ cú pháp quan trọng để triển khai phương thức trên một cấu trúc tổng quát: bạn cần viết impl<T> trước MyBox<T> để cho Rust biết rằng T là tham số tổng quát cho toàn bộ khối triển khai.

Trong tệp chính, hãy minh họa MyBox bằng cách:

  1. Tạo một hộp chứa số nguyên (đầu vào thứ nhất, được phân tích thành i32)
  2. Xem nội dung bên trong và in giá trị ra
  3. Thay thế nội dung bằng một số nguyên mới (đầu vào thứ hai, được phân tích thành i32)
  4. Xem lại nội dung để hiển thị giá trị đã cập nhật
  5. Tạo hộp thứ hai chứa chuỗi (đầu vào thứ ba)
  6. Xem nội dung bên trong hộp chứa chuỗi

Đầu ra của bạn phải theo định dạng sau:

Integer box contains: {value}
After replace: {value}
String box contains: {value}

Ví dụ, với các đầu vào 10, 25 và Rust:

Integer box contains: 10
After replace: 25
String box contains: Rust

Bạn sẽ nhận ba đầu vào: một số nguyên ban đầu, một số nguyên thay thế và một giá trị chuỗi.

Tự làm thử

mod mybox;

use mybox::MyBox;

fn main() {
    // Đọc dữ liệu đầu vào
    let mut input1 = String::new();
    std::io::stdin().read_line(&mut input1).expect("Failed to read line");
    let initial_int: i32 = input1.trim().parse().expect("Invalid integer");

    let mut input2 = String::new();
    std::io::stdin().read_line(&mut input2).expect("Failed to read line");
    let replacement_int: i32 = input2.trim().parse().expect("Invalid integer");

    let mut input3 = String::new();
    std::io::stdin().read_line(&mut input3).expect("Failed to read line");
    let string_value = input3.trim().to_string();

    // TODO: Tạo một MyBox chứa số nguyên ban đầu
    
    // TODO: Xem nội dung của nó và in ra: "Integer box contains: {value}"
    
    // TODO: Thay nội dung bằng số nguyên thay thế
    
    // TODO: Xem lại và in ra: "After replace: {value}"
    
    // TODO: Tạo MyBox thứ hai chứa giá trị chuỗi
    
    // TODO: Xem nội dung của hộp chuỗi và in ra: "String box contains: {value}"
}
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