Các trait so sánh bằng
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 38 trên 61.
Trong Rust, theo mặc định, bạn không thể so sánh hai đối tượng của một struct tùy chỉnh bằng ==. Trình biên dịch không biết cách xác định hai struct có bằng nhau hay không. Bạn cần cho trình biên dịch biết bằng cách triển khai trait PartialEq.
Giống như Debug và Copy, bạn có thể tự động suy ra PartialEq:
#[derive(PartialEq)]
struct Coordinate {
x: i32,
y: i32,
}
let a = Coordinate { x: 5, y: 10 };
let b = Coordinate { x: 5, y: 10 };
let c = Coordinate { x: 3, y: 7 };
println!("{}", a == b); // true
println!("{}", a == c); // false
Khi được tự động tạo, PartialEq sẽ so sánh từng trường của struct. Hai instance chỉ bằng nhau khi tất cả các trường tương ứng đều trùng khớp.
Bạn cũng sẽ gặp Eq, đây là một trait đánh dấu, cho biết tính bằng nhau toàn phần, nghĩa là mọi giá trị đều bằng chính nó. Hầu hết các kiểu đều thỏa mãn điều này, nhưng số dấu phẩy động thì không (vì NaN != NaN). Với các struct có trường kiểu số nguyên, bạn có thể dẫn xuất an toàn cả hai trait:
#[derive(PartialEq, Eq)]
struct Coordinate {
x: i32,
y: i32,
}
Eq không có phương thức riêng. Nó chỉ báo hiệu rằng kiểu dữ liệu có tính đẳng thức phản xạ. Một số tính năng trong thư viện chuẩn yêu cầu Eq bên cạnh PartialEq, vì vậy các kiểu dữ liệu đáp ứng điều kiện thường được suy diễn cả hai trait cùng lúc.
Thử thách
DễHãy xây dựng một hệ thống so khớp màu để minh họa cách các trait PartialEq và Eq cho phép so sánh các instance của struct!
Bạn sẽ tạo hai tệp để sắp xếp logic so sánh màu:
color.rs: Định nghĩa một structColorcông khai với ba trường công khai:red,greenvàblue(đều có kiểuu8). Dẫn xuất cảPartialEqvàEqđể có thể so sánh hai màu bằng==. Khi được dẫn xuất, Rust chỉ xem hai màu là bằng nhau nếu cả ba thành phần RGB khớp chính xác.main.rs: Đưa module màu vào và tạo hai instanceColorbằng các đầu vào đã cho. So sánh chúng bằng==rồi in ra liệu chúng có khớp hay không.
Đầu ra của bạn cần cho biết hai màu có giống nhau hay không:
Color 1: rgb({r1}, {g1}, {b1})
Color 2: rgb({r2}, {g2}, {b2})
Colors match: {true/false}Ví dụ, với các đầu vào 255, 128, 0, 255, 128, 0:
Color 1: rgb(255, 128, 0)
Color 2: rgb(255, 128, 0)
Colors match: trueVà với các đầu vào 100, 100, 100, 200, 200, 200:
Color 1: rgb(100, 100, 100)
Color 2: rgb(200, 200, 200)
Colors match: falseBạn sẽ nhận sáu đầu vào: các giá trị RGB của màu thứ nhất (ba giá trị), tiếp theo là các giá trị RGB của màu thứ hai (ba giá trị). Phân tích mỗi giá trị thành u8.
Tự làm thử
mod color;
use color::Color;
fn main() {
// Đọc sáu giá trị RGB
let mut input = String::new();
std::io::stdin().read_line(&mut input).expect("Failed to read line");
let r1: u8 = input.trim().parse().expect("Invalid input");
input.clear();
std::io::stdin().read_line(&mut input).expect("Failed to read line");
let g1: u8 = input.trim().parse().expect("Invalid input");
input.clear();
std::io::stdin().read_line(&mut input).expect("Failed to read line");
let b1: u8 = input.trim().parse().expect("Invalid input");
input.clear();
std::io::stdin().read_line(&mut input).expect("Failed to read line");
let r2: u8 = input.trim().parse().expect("Invalid input");
input.clear();
std::io::stdin().read_line(&mut input).expect("Failed to read line");
let g2: u8 = input.trim().parse().expect("Invalid input");
input.clear();
std::io::stdin().read_line(&mut input).expect("Failed to read line");
let b2: u8 = input.trim().parse().expect("Invalid input");
// TODO: Tạo hai instance Color bằng các giá trị đã phân tích
// TODO: In Color 1 theo định dạng: Color 1: rgb(r, g, b)
// TODO: In Color 2 theo định dạng: Color 2: rgb(r, g, b)
// TODO: So sánh hai màu bằng == rồi in ra: Colors match: {true/false}
}
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