乐趣区

关于rust:实践解析丨Rust-内置-traitPartialEq-和-Eq

摘要:Rust 在很多中央应用了 traits, 从十分通俗的操作符重载, 到 Send, Sync 这种十分奥妙的个性。

本文分享自华为云社区《Rust 内置 trait 解析:PartialEq 和 Eq》,原文作者:debugzhang

Rust 在很多中央应用了 traits, 从十分通俗的操作符重载, 到 Send, Sync 这种十分奥妙的个性。一些 traits 是能够被主动派生的(你只须要写 #[derive(Copy, Clone, PartialEq, Eq, Debug, Default, Hash, …)] 就能失去一个神奇的实现, 它通常是对的。

PartialEq 和 Eq 这两个 Traits 的名称实际上来自于抽象代数中的等价关系和部分等价关系,实际上两者的区别仅有一点,即是否在相等比拟中是否满足反身性(Reflexivity)。

PartialEq

/// [`eq`]: PartialEq::eq
/// [`ne`]: PartialEq::ne
#[lang = "eq"]
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(alias = "==")]
#[doc(alias = "!=")]
#[rustc_on_unimplemented(message = "can't compare `{Self}` with `{Rhs}`",
    label = "no implementation for `{Self} == {Rhs}`"
)]
pub trait PartialEq<Rhs: ?Sized = Self> {
    /// This method tests for `self` and `other` values to be equal, and is used
    /// by `==`.
    #[must_use]
    #[stable(feature = "rust1", since = "1.0.0")]
    fn eq(&self, other: &Rhs) -> bool;

    /// This method tests for `!=`.
    #[inline]
    #[must_use]
    #[stable(feature = "rust1", since = "1.0.0")]
    fn ne(&self, other: &Rhs) -> bool {!self.eq(other)
    }
}

如果咱们想比拟某个类型的两个值 x 和 y 是否相等(不等),例如:x == y (x != y),那么咱们就必须为类型实现 PartialEq Trait。

PartialEq 可应用 #[derive] 来交由编译器实现,当一个 struct 在进行相等比拟时,会对其中每一个字段进行比拟;如果遇到枚举时,还会对枚举所领有的数据进行比拟。

咱们也能够本人实现 PartialEq,实现时只须要实现判断是否相等的函数 fn eq(&self, other: &Self) -> bool,Rust 会主动提供 fn ne(&self, other: &Self) -> bool。例子如下:

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}
}

Eq

pub trait Eq: PartialEq<Self> {// this method is used solely by #[deriving] to assert
    // that every component of a type implements #[deriving]
    // itself, the current deriving infrastructure means doing this
    // assertion without using a method on this trait is nearly
    // impossible.
    //
    // This should never be implemented by hand.
    #[doc(hidden)]
    #[inline]
    #[stable(feature = "rust1", since = "1.0.0")]
    fn assert_receiver_is_total_eq(&self) {}}

实现 Eq 的前提是曾经实现了 PartialEq,因为实现 Eq 不须要额定的代码,只须要在实现了 PartialEq 的根底上通知编译器它的比拟满足自反性就能够了。对于下面的例子只须要:#[derive(Eq)] 或 impl Eq for Book {}。

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}
}

impl Eq for Book {}

PartialEq 和 Eq

这两个 Traits 的名称实际上来自于抽象代数中的等价关系和部分等价关系。

等价关系(equivalence relation)即设 displaystyle R_R_ 是某个汇合 displaystyle A_A_ 上的一个二元关系。若 displaystyle R_R_ 满足以下条件:

则称 displaystyle R_R_ 是一个定义在 displaystyle A_A_ 上的 等价关系

并非所有的二元关系都是等价关系,Eq 和 PartialEq 的区别在于是否在相等比拟中是否满足自反性,即 x == x。

例如对于浮点类型,Rust 只实现了 PartialEq 而没有实现 Eq,起因在于 NaN != Nan,不满足自反性。

Eq 相比 PartialEq 须要额定满足反身性,即 a == a,对于浮点类型,Rust 只实现了 PartialEq 而不是 Eq,起因就是 NaN != NaN。

Eq 和 Hash

当一个类型同时实现了 Eq 和 Hash 时,该类型满足下列个性:

k1 == k2 -> hash(k1) == hash(k2)

即,当两个 key 相等时,它们的哈希值必然相等。Rust 里的 HashMap 和 HashSet 都依赖该个性。

点击关注,第一工夫理解华为云陈腐技术~

退出移动版