Chuyển đến nội dung chính
Mô-đun 5 · Bài học 1 trong tổng số 29/14 trong khóa học~12 min
Bài học theo mô-đun (1/2)

Generics và chức năng

Generics cho phép bạn viết mã linh hoạt, có thể tái sử dụng, tránh trùng lặp logic cho các loại dữ liệu khác nhau. Thay vì xác định nhiều hàm hoặc cấu trúc cho các loại khác nhau (như i32, f64 hoặc String), chúng ta có thể sử dụng tham số loại chung, thường được biểu thị bằng chữ cái T.

Trình biên dịch Rust quản lý các generic bằng cách sử dụng một quy trình có tên monomorphization: trong quá trình biên dịch, nó tạo ra một bản sao của mã chung cho từng loại cụ thể được sử dụng thực sự. Điều này có nghĩa là không có chi phí về hiệu năng thời gian chạy.


Hàm chung

Để xác định hàm chung, chúng ta chèn tham số loại <T> ngay sau tên hàm và trước danh sách đối số:

Rust
fn print_value<T: std::fmt::Debug>(value: T) {
    println!("Value: {:?}", value);
}

Trong các hàm chung, chúng ta có thể sử dụng kiểu chung T cho cả kiểu đối số và kiểu trả về:

Rust
fn identity<T>(value: T) -> T {
    value
}

Cấu trúc chung

Chúng ta cũng có thể sử dụng các tham số loại chung bên trong các cấu trúc (struct) để xác định các trường linh hoạt:

Rust
struct KeyValuePair<K, V> {
    key: K,
    value: V,
}

fn main() {
    let pair = KeyValuePair {
        key: String::from("age"),
        value: 30,
    };
}

Trong khối impl cho cấu trúc chung, chúng ta phải khai báo tham số loại <T> ngay sau từ khóa impl để cho biết chúng ta đang triển khai các phương thức trên cấu trúc chung:

Rust
struct Container<T> {
    value: T,
}

impl<T> Container<T> {
    fn new(value: T) -> Self {
        Container { value }
    }

    fn value(&self) -> &T {
        &self.value
    }
}

Hãy tự mình thử

Bài tập 1: Cấu trúc điểm

tập thể dục#rust.m5.l1.e1
Nỗ lực: 0Đang tải…

Xác định một cấu trúc chung có tên Point<T> với hai trường: x thuộc loại T và y thuộc loại T. Trong hàm chính, khởi tạo một biến point chứa Point có giá trị nguyên x = 5 và y = 10, sau đó in giá trị của point.x.

Đang tải trình chỉnh sửa…
Hiển thị gợi ý

Khai báo cấu trúc bằng cách sử dụng `struct Point<T> { x: T, y: T }`. Khởi tạo nó trong main và sử dụng `point.x` để in nó.

Giải pháp khả dụng sau 3 lần thử

Bài tập 2: Đảo ngược Tuple bằng swap

tập thể dục#rust.m5.l1.e2
Nỗ lực: 0Đang tải…

Viết một hàm tổng quát có tên swap<T> chấp nhận một bộ gồm hai phần tử (T, T) và trả về một bộ mới (T, T) với vị trí của chúng bị đảo ngược. Trong hàm chính, gọi hàm với bộ dữ liệu (1, 2) và in kết quả.

Đang tải trình chỉnh sửa…
Hiển thị gợi ý

Chữ ký hàm phải là `fn swap<T>(pair: (T, T)) -> (T, T)`. Trả về bộ dữ liệu đã đảo ngược với `(pair.1, pair.0)`.

Giải pháp khả dụng sau 3 lần thử

Bài tập 3: Cấu trúc container

tập thể dục#rust.m5.l1.e3
Nỗ lực: 0Đang tải…

Xác định một cấu trúc chung Container<T> chứa trường giá trị loại T. Triển khai khối impl chung để xác định một phương thức mới chấp nhận giá trị loại T và trả về một thể hiện của Container<T>.

Đang tải trình chỉnh sửa…
Hiển thị gợi ý

Sử dụng `impl<T> Container<T>`để triển khai phương thức được liên kết`fn new(value: T) -> Self { Container { value } }`.

Giải pháp khả dụng sau 3 lần thử