Rust笔记 - PartialEq && Eq

1,593 阅读1分钟

什么是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可以比较部分成员,更加灵活。