什么是PartialEq呢?不如先看一个例子先:
fn main() {
assert!(f64::is_nan(0.0/0.0));
assert_eq!(0.0/0.0 == 0.0/0.0, false);
assert_eq!(0.0/0.0 != 0.0/0.0, true);
}
上面的断言都能正确通过。为什么都能正确通过呢?不是有点反直觉吗?先别急,因为浮点数在计算机里表示为IEEE floating-point values。简单的说就是,浮点数是有精度的,计算机无法表示很精确的小数。Rust为了比较浮点数特地弄了个partialEq 。而Eq则是完全相等。下面看一下它们的trait:
trait PartialEq<Rhs: ?Sized = Self> {
fn eq(&self, other: &Rhs) -> bool;
fn ne(&self, other: &Rhs) -> bool { !self.eq(other) }
}
trait Eq: PartialEq<Self> { }
因为是通过引用传递参数,所以Rhs的类型可以是?Sized的。
下面通过一个例子实现这两个trait:
use std::cmp::PartialEq;
struct Any<T, U> {
index: T,
content: U,
}
impl<T, U> PartialEq for Any<T, U>
where
U: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.content == other.content
}
}
impl<T: Eq, U: Eq> Eq for Any<T, U> { }
fn main() {
let a = Any {
index: 1,
content: "shell".to_owned(),
};
let b = Any {
index: 2,
content: "shell".to_owned(),
};
assert!(a == b);
}
值得注意的是,Eq trait 是空的,用于trait bounds,限制类型的使用。
更多时候我们是通过derive方式来实现它们:
use std::cmp::PartialEq;
#[derive(PartialEq, Eq)]
struct Any<T, U> {
index: T,
content: U,
}
fn main() {
let a = Any {
index: 1,
content: "shell".to_owned(),
};
let b = Any {
index: 1,
content: "shell".to_owned(),
};
assert!(a == b);
}
使用derive实现默认是比较全部成员,而自己实现trait可以比较部分成员,更加灵活。