相等性 Trait
本课属于 Coddy Rust 学习旅程的“面向对象编程”单元。第 38 课,共 61 课。
在 Rust 中,默认情况下,无法使用 == 比较两个自定义结构体实例。编译器不知道如何判断两个结构体是否相等。你需要实现 PartialEq 特征来告诉编译器。
和 Debug、Copy 一样,你可以自动派生 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
派生 PartialEq 时,会比较结构体的每个字段。只有所有对应字段都匹配时,两个实例才相等。
你还会遇到 Eq,它是一种标记特征,表示完全相等,也就是说,每个值都等于自身。大多数类型都满足这一点,但浮点数不满足(因为 NaN != NaN)。对于包含整数属性的结构体,你可以安全地派生这两种特征:
#[derive(PartialEq, Eq)]
struct Coordinate {
x: i32,
y: i32,
}
Eq 没有自己的方法。它只是表示该类型具有自反相等性。一些标准库功能除了要求 PartialEq,还要求 Eq,因此对于符合条件的类型,通常会同时派生这两个特征。
挑战
简单让我们构建一个颜色匹配系统,演示 PartialEq 和 Eq trait 如何支持比较结构体实例!
你将创建两个文件来整理颜色比较逻辑:
color.rs:定义一个公共的Color结构体,其中包含三个公共字段:red、green和blue(类型均为u8)。派生PartialEq和Eq,这样就可以使用==比较两个颜色。派生这两个 trait 后,Rust 只有在三个 RGB 分量完全匹配时,才会认为两个颜色相等。main.rs:引入颜色模块,并使用提供的输入创建两个Color实例。使用==比较它们,并输出它们是否匹配。
输出应说明这两个颜色是否相同:
Color 1: rgb({r1}, {g1}, {b1})
Color 2: rgb({r2}, {g2}, {b2})
Colors match: {true/false}例如,输入 255、128、0、255、128、0 时:
Color 1: rgb(255, 128, 0)
Color 2: rgb(255, 128, 0)
Colors match: true输入 100、100、100、200、200、200 时:
Color 1: rgb(100, 100, 100)
Color 2: rgb(200, 200, 200)
Colors match: false你将收到 6 个输入:第一个颜色的 RGB 值(3 个值),接着是第二个颜色的 RGB 值(3 个值)。将每个值解析为 u8。
亲手试试
mod color;
use color::Color;
fn main() {
// 读取 6 个 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: 用解析出的值创建两个 Color 实例
// TODO: 按以下格式打印 Color 1:Color 1: rgb(r, g, b)
// TODO: 按以下格式打印 Color 2:Color 2: rgb(r, g, b)
// TODO: 用 == 比较这两种颜色,并打印:Colors match: {true/false}
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Rust 在线编译器