Trait Debug
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 35 trên 61.
Thư viện chuẩn của Rust có nhiều trait được định nghĩa sẵn, cung cấp các chức năng phổ biến. Một trong những trait hữu ích nhất khi phát triển là trait Debug, cho phép bạn in nội dung của một struct để kiểm tra.
Nếu bạn thử in trực tiếp một struct tùy chỉnh, Rust sẽ không biết cách hiển thị nó:
struct Player {
name: String,
score: u32,
}
let p = Player { name: String::from("Alice"), score: 100 };
println!("{:?}", p); // Lỗi! Chưa triển khai Debug
Bộ định dạng {:?} yêu cầu trait Debug. Thay vì tự triển khai trait này, Rust cung cấp một cách viết tắt: thuộc tính #[derive]. Đặt thuộc tính này ngay phía trên định nghĩa struct của bạn:
#[derive(Debug)]
struct Player {
name: String,
score: u32,
}
let p = Player { name: String::from("Alice"), score: 100 };
println!("{:?}", p); // Player { name: "Alice", score: 100 }
Thuộc tính #[derive(Debug)] yêu cầu trình biên dịch tự động tạo phần triển khai Debug. Cách này hoạt động miễn là mọi trường trong struct của bạn cũng triển khai Debug (hầu hết các kiểu dữ liệu tiêu chuẩn đều làm được).
Để đầu ra dễ đọc hơn khi có cấu trúc lồng nhau, hãy dùng {:#?} để in đẹp:
println!("{:#?}", p);
// Player {
// name: "Alice",
// score: 100,
// }
Việc dẫn xuất Debug rất cần thiết trong quá trình phát triển. Nhờ đó, bạn có thể nhanh chóng kiểm tra dữ liệu mà không cần viết code định dạng riêng.
Thử thách
DễHãy giúp các struct có thể kiểm tra được bằng cách suy diễn trait Debug nhé! Bạn sẽ tạo một hệ thống kiểm kê đơn giản, trong đó các mặt hàng có thể được in ra để phục vụ việc gỡ lỗi.
Bạn sẽ sắp xếp code trong hai tệp:
inventory.rs: Định nghĩa structItemcông khai với hai trường công khai:name(String) vàquantity(u32). Dùng thuộc tính#[derive(Debug)]để tự động triển khai trait Debug cho struct của bạn.main.rs: Đưa module inventory vào và tạo một instanceItembằng các đầu vào đã cho. In mặt hàng bằng bộ định dạng gỡ lỗi{:?}để hiển thị cấu trúc bên trong của nó.
Điểm hay của việc suy diễn Debug là Rust tự động tạo code định dạng cho bạn, không cần triển khai thủ công! Struct chỉ cần có thuộc tính này là có thể in ra bằng {:?}.
Đầu ra cần hiển thị mặt hàng theo định dạng gỡ lỗi của Rust:
Item { name: "{name}", quantity: {quantity} }Ví dụ, với đầu vào Keyboard và 15:
Item { name: "Keyboard", quantity: 15 }Bạn sẽ nhận hai đầu vào: tên mặt hàng và số lượng (phân tích thành u32).
Tự làm thử
mod inventory;
use inventory::Item;
fn main() {
// Đọc đầu vào
let mut name = String::new();
std::io::stdin().read_line(&mut name).expect("Failed to read line");
let name = name.trim().to_string();
let mut quantity_str = String::new();
std::io::stdin().read_line(&mut quantity_str).expect("Failed to read line");
let quantity: u32 = quantity_str.trim().parse().expect("Failed to parse quantity");
// TODO: Tạo một instance Item với tên và số lượng đã cho
// TODO: In mục hàng bằng bộ định dạng gỡ lỗi {:?}
}
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