当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


Rust PartialEq用法及代码示例


本文简要介绍rust语言中 Trait std::cmp::PartialEq 的用法。

用法

pub trait PartialEq<Rhs = Self> where    Rhs: ?Sized, {
    fn eq(&self, other: &Rhs) -> bool;

    fn ne(&self, other: &Rhs) -> bool { ... }
}

相等比较的特征是 partial equivalence relations

x.eq(y) 也可以写成 x == yx.ne(y) 可以写成 x != y 。我们在本文档的其余部分使用easier-to-read 中缀表示法。

对于不具有完全等价关系的类型,此特征允许部分相等。例如,在浮点数 NaN != NaN 中,浮点类型实现了 PartialEq 而不是 Eq

实现必须确保eqne 彼此一致:

  • a != b 当且仅当 !(a == b)(由默认实现确保)。

如果 PartialOrd Ord 也为 SelfRhs 实现,它们的方法也必须与 PartialEq 一致(有关确切要求,请参阅这些特征的文档)。通过派生一些特征并手动实现其他特征,很容易意外地使他们不同意。

等式关系==必须满足以下条件(对于所有类型为ABCabc):

  • 对称的: 如果A: PartialEq<B>B: PartialEq<A>, 然后a == b 意味着b == a;和

  • 传递的: 如果A: PartialEq<B>B: PartialEq<C>A: PartialEq<C>, 然后a == bb == c 意味着 a == c.

请注意,B: PartialEq<A>(对称)和A: PartialEq<C>(传递)impls 不是强制存在的,但只要它们确实存在,这些要求就适用。

可导出的

此特征可与 #[derive] 一起使用。当 derive d 在结构上时,如果所有字段相等,则两个实例相等,如果任何字段不相等,则不相等。当 derive d 在枚举上时,每个变体都等于自身,而不等于其他变体。

如何实现 PartialEq

一个域的示例实现,其中两本书如果 ISBN 匹配则被视为同一本书,即使格式不同:

enum BookFormat {
    Paperback,
    Hardback,
    Ebook,
}

struct Book {
    isbn: i32,
    format: BookFormat,
}

impl PartialEq for Book {
    fn eq(&self, other: &Self) -> bool {
        self.isbn == other.isbn
    }
}

let b1 = Book { isbn: 3, format: BookFormat::Paperback };
let b2 = Book { isbn: 3, format: BookFormat::Ebook };
let b3 = Book { isbn: 10, format: BookFormat::Paperback };

assert!(b1 == b2);
assert!(b1 != b3);

如何比较两种不同的类型?

您可以比较的类型由 PartialEq 的类型参数控制。例如,让我们稍微调整一下我们之前的代码:

// The derive implements <BookFormat> == <BookFormat> comparisons
#[derive(PartialEq)]
enum BookFormat {
    Paperback,
    Hardback,
    Ebook,
}

struct Book {
    isbn: i32,
    format: BookFormat,
}

// Implement <Book> == <BookFormat> comparisons
impl PartialEq<BookFormat> for Book {
    fn eq(&self, other: &BookFormat) -> bool {
        self.format == *other
    }
}

// Implement <BookFormat> == <Book> comparisons
impl PartialEq<Book> for BookFormat {
    fn eq(&self, other: &Book) -> bool {
        *self == other.format
    }
}

let b1 = Book { isbn: 3, format: BookFormat::Paperback };

assert!(b1 == BookFormat::Paperback);
assert!(BookFormat::Ebook != b1);

通过将 impl PartialEq for Book 更改为 impl PartialEq<BookFormat> for Book ,我们允许将 BookFormat s 与 Book s 进行比较。

像上面这样忽略结构的某些字段的比较可能很危险。它很容易导致意外违反部分等价关系的要求。例如,如果我们为BookFormat 保留上述PartialEq<Book> 的实现,并为Book 添加PartialEq<Book> 的实现(通过#[derive] 或通过第一个示例中的手动实现),那么结果将违反传递性:

#[derive(PartialEq)]
enum BookFormat {
    Paperback,
    Hardback,
    Ebook,
}

#[derive(PartialEq)]
struct Book {
    isbn: i32,
    format: BookFormat,
}

impl PartialEq<BookFormat> for Book {
    fn eq(&self, other: &BookFormat) -> bool {
        self.format == *other
    }
}

impl PartialEq<Book> for BookFormat {
    fn eq(&self, other: &Book) -> bool {
        *self == other.format
    }
}

fn main() {
    let b1 = Book { isbn: 1, format: BookFormat::Paperback };
    let b2 = Book { isbn: 2, format: BookFormat::Paperback };

    assert!(b1 == BookFormat::Paperback);
    assert!(BookFormat::Paperback == b2);

    // The following should hold by transitivity but doesn't.
    assert!(b1 == b2); // <-- PANICS
}

例子

let x: u32 = 0;
let y: u32 = 1;

assert_eq!(x == y, false);
assert_eq!(x.eq(&y), false);

相关用法


注:本文由纯净天空筛选整理自rust-lang.org大神的英文原创作品 Trait std::cmp::PartialEq。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。