Trait Drop
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 56 trên 61.
Khi một giá trị ra khỏi phạm vi trong Rust, nó sẽ tự động được dọn dẹp. Nhưng nếu bạn cần chạy code tùy chỉnh vào lúc đó, chẳng hạn như ghi nhật ký, giải phóng tài nguyên hoặc gửi thông báo cuối cùng thì sao? Trait Drop cho phép bạn xác định chính xác điều gì xảy ra khi struct sắp bị hủy.
Trait Drop có một phương thức duy nhất tên là drop, nhận &mut self:
struct Connection {
id: u32,
}
impl Drop for Connection {
fn drop(&mut self) {
println!("Connection {} closed.", self.id);
}
}
Bạn không bao giờ gọi trực tiếp drop: Rust tự động gọi hàm này khi giá trị ra khỏi phạm vi:
fn main() {
let conn = Connection { id: 42 };
println!("Using connection...");
} // "Connection 42 closed." tự động in ra ở đây
Đầu ra sẽ là:
Using connection...
Connection 42 closed.
Đây là phiên bản hàm hủy (destructor) của Rust. Hàm này thường dùng cho các tác vụ dọn dẹp: đóng handle tệp, ngắt kết nối với máy chủ hoặc giải phóng tài nguyên mà Rust không thể tự quản lý. Trait Drop đảm bảo code dọn dẹp của bạn vẫn chạy, kể cả khi phạm vi kết thúc do lệnh return sớm.
Thử thách
DễHãy xây dựng một hệ thống quản lý tài nguyên minh họa cách tự động dọn dẹp! Bạn sẽ tạo một struct FileHandle mô phỏng việc mở và đóng tệp. Khi handle ra khỏi phạm vi, nó sẽ tự động thông báo rằng tệp đã đóng.
Bạn sẽ tổ chức code trong hai tệp:
file_handle.rs: Định nghĩa một structFileHandlecông khai với trườngfilenamecông khai (String). Triển khai hàm liên kếtnewđể tạo một FileHandle và in thông báo khi tệp được "opened". Sau đó, triển khai traitDropđể khi handle bị loại bỏ, nó sẽ in thông báo đóng tệp.main.rs: Đưa module file_handle vào và tạo hàm tên làprocess_filenhận một filename, tạo một FileHandle bên trong phạm vi cục bộ và in thông báo xử lý khi tệp đang "open". Phần triển khai Drop sẽ tự động chạy khi phạm vi kết thúc. Gọi hàm này với đầu vào đã cho.
Khi tạo FileHandle, chương trình sẽ in:
Opening file: {filename}Trong khi xử lý (bên trong phạm vi), hãy in:
Processing {filename}...Khi FileHandle bị loại bỏ (phạm vi kết thúc), chương trình sẽ in:
Closing file: {filename}Ví dụ, với đầu vào data.txt:
Opening file: data.txt
Processing data.txt...
Closing file: data.txtVà với đầu vào config.json:
Opening file: config.json
Processing config.json...
Closing file: config.jsonBạn sẽ nhận một đầu vào: chuỗi tên tệp.
Tự làm thử
mod file_handle;
use file_handle::FileHandle;
// TODO: Triển khai hàm (function) process_file
// Hàm này cần:
// 1. Tạo một phạm vi cục bộ (dùng dấu ngoặc nhọn {})
// 2. Trong phạm vi đó, tạo một FileHandle bằng FileHandle::new()
// 3. In ra thông báo xử lý: "Processing {filename}..."
// 4. Khi phạm vi kết thúc, Drop sẽ tự động được gọi
fn process_file(filename: &str) {
// TODO: Triển khai hàm này
}
fn main() {
let mut input = String::new();
std::io::stdin().read_line(&mut input).expect("Failed to read line");
let filename = input.trim();
process_file(filename);
}
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
1Phương thức và hành vi
Nhập môn khối triển khaiTham số selfPhương thức có thể thay đổiHàm liên kếtNhiều khối triển khaiNối chuỗi phương thứcÔn tập: thao tác với hình chữ nhật4Dự án: Thú cưng ảo
Định nghĩa thú cưngCho thú cưng ăn7Các trait tiêu chuẩn
Trait DebugTrait DisplayClone và CopyCác trait so sánh bằngÔn tập: Điểm có thể in ra2Tính đóng gói và module
Kiến thức cơ bản về moduleTừ khóa publicTrường riêng tưHàm lấy giá trịHàm thiết lập giá trịÔn tập: tủ khóa an toàn5Kiểu tổng quát
Cấu trúc tổng quátPhương thức tổng quátNhiều kiểu tổng quátHàm tổng quátÔn tập: điểm tọa độTự luyện tập: Trình biên dịch Rust online