Trait std::cmp::PartialEq1.0.0[][src]

pub trait PartialEq<Rhs = Self> where
    Rhs: ?Sized
{ #[must_use] fn eq(&self, other: &Rhs) -> bool; #[must_use] fn ne(&self, other: &Rhs) -> bool { ... } }
Expand description

等值比较器的 Trait 为 部分等价关系

x.eq(y) 也可以写成 x == yx.ne(y) 可以写成 x != y。 我们在本文档的其余部分使用更易于阅读的中缀符号。

trait 允许部分相等,用于不具有完全等价关系的类型。 例如,在浮点数 NaN != NaN 中,因此浮点类型实现 PartialEq,但不实现 Eq

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

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

如果 SelfRhs 也实现了 PartialOrdOrd,则它们的方法也必须与 PartialEq 一致 (具体要求请参见那些 traits 的文档)。 通过派生一些 traits 并手动实现其他一些行为,很容易使它们不以为然。

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

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

  • 可传递: 如果 A: PartialEq<B>B: PartialEq<C> 以及 A: 偏等式 <C>,然后 a == b,而 b == c 表示a == c

请注意,B: PartialEq<A> (symmetric) 和 A: PartialEq<C> (transitive) 强制不是强制存在的,但是这些要求只要存在就适用。

Derivable

该 trait 可以与 #[derive] 一起使用。在结构体上 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);
Run

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

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

// 衍生工具 <BookFormat> == <BookFormat> 比较
#[derive(PartialEq)]
enum BookFormat {
    Paperback,
    Hardback,
    Ebook,
}

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

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

// 实现 <BookFormat> == <Book> 比较
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);
Run

通过将 impl PartialEq for Book 更改为 impl PartialEq<BookFormat> for Book,我们可以将 BookFormat 和 Book 进行比较。

像上面这样的比较 (它忽略了结构体的某些字段) 可能很危险。这很容易导致意外违反部分对等关系的要求。 例如,如果我们保留了以上针对 BookFormatPartialEq<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);

    // 以下应该通过传递性来保持,但不是。
    assert!(b1 == b2); // <-- PANICS
}
Run

Examples

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

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

Required methods

此方法测试 selfother 值是否相等,并由 == 使用。

Provided methods

此方法测试 !=

Implementations on Foreign Types

Implementors

Panics

如果当前借用了任一 RefCell 中的值,则会出现 panic。

两个 Rc 相等。

即使两个 Rc 的内部值相等,即使它们存储在不同的分配中,它们也相等。

如果 T 还实现了 Eq (暗示相等的自反性),则指向同一分配的两个 `Rc’ 始终相等。

Examples

use std::rc::Rc;

let five = Rc::new(5);

assert!(five == Rc::new(5));
Run

两个 Rc 的不等式。

如果两个 Rc 的内部值不相等,则它们是不相等的。

如果 T 还实现了 Eq (暗示相等性的反射性),则指向同一分配的两个 Rc 永远不会相等。

Examples

use std::rc::Rc;

let five = Rc::new(5);

assert!(five != Rc::new(6));
Run

两个 Arc 的相等性。

即使两个 Arc 的内部值相等,即使它们存储在不同的分配中,它们也相等。

如果 T 还实现了 Eq (暗示相等的自反性),则指向同一分配的两个 Arc 始终相等。

Examples

use std::sync::Arc;

let five = Arc::new(5);

assert!(five == Arc::new(5));
Run

两个 Arc 的不等式。

如果两个 Arc 的内部值不相等,则它们是不相等的。

如果 T 还实现了 Eq (暗示相等性的反射性),则指向相同值的两个 `Arc’ 永远不会相等。

Examples

use std::sync::Arc;

let five = Arc::new(5);

assert!(five != Arc::new(6));
Run