GitHub: https://github.com/storagezhang

Emai: debugzhang@163.com

华为云社区: https://bbs.huaweicloud.com/blogs/250275

Eq and PartialEq are traits that allow you to define total and partial equality between values, respectively. Implementing them overloads the == and != operators.

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\) 是某个集合 \(\displaystyle A\) 上的一个二元关系。若 \(\displaystyle R\) 满足以下条件:

  1. 自反性:\(\displaystyle \forall x\in A,~~xRx\)
  2. 对称性:\(\displaystyle \forall x,y\in A,~~xRy~~\implies ~~yRx\)
  3. 传递性:\(\displaystyle \forall x,y,z\in A,~~~(xRy~~\wedge ~~yRz)~~\implies ~~xRz\)

则称 \(\displaystyle R\) 是一个定义在 \(\displaystyle A\) 上的等价关系

并非所有的二元关系都是等价关系, EqPartialEq 的区别在于是否在相等比较中是否满足自反性,即 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 都依赖该特性。

Rust 内置 trait :PartialEq 和 Eq的更多相关文章

  1. 实践解析丨Rust 内置 trait:PartialEq 和 Eq

    摘要:Rust 在很多地方使用了 traits, 从非常浅显的操作符重载, 到 Send, Sync 这种非常微妙的特性. Rust 在很多地方使用了 traits, 从非常浅显的操作符重载, 到 S ...

  2. Python进阶-XVIV 类的内置方法:__str__ 、__repr__、析构函数(__del__)、双下的call,eq,new,hash 以及item相关的三个方法

    类的内置方法 它与内置函数有紧密的联系,有的内置函数就是调用的内置方法. 在顶级父类obj中有: 两个双下方法 obj.__str__ str(obj) obj.__repr__ repr(obj) ...

  3. Perl语言中一些内置变量等,$x、qw、cmp、eq、ne等

    转载 Perl语言中一些内置变量等,$x.qw.cmp.eq.ne等 字母 符号 释义 eq  = = equal(等于) ne != not equal(不等于) cmp 比较 qq  " ...

  4. TODO:Laravel 内置简单登录

    TODO:Laravel 内置简单登录 1. 激活Laravel的Auth系统Laravel 利用 PHP 的新特性 trait 内置了非常完善好用的简单用户登录注册功能,适合一些不需要复杂用户权限管 ...

  5. php 内置支持的标签和属性

    内置支持的标签和属性列表如下: 标签名 作用 包含属性 include 包含外部模板文件(闭合) file import 导入资源文件(闭合 包括js css load别名) file,href,ty ...

  6. thinkphp 内置标签volist 控制换行

    thinkphp 内置标签volist 控制换行 volist标签通常用于查询数据集(select方法)的结果输出,通常模型的select方法返回的结果是一个二维数组,可以直接使用volist标签进行 ...

  7. include(thinkphp常用内置标签)

    变量输出使用普通标签就足够了,但是要完成其他的控制.循环和判断功能,就需要借助模板引擎的标签库功能了,系统内置标签库的所有标签无需引入标签库即可直接使用. XML标签有两种,包括闭合标签和开放标签,一 ...

  8. 前端MVC学习总结(三)——AngularJS服务、路由、内置API、jQueryLite

    一.服务 AngularJS功能最基本的组件之一是服务(Service).服务为你的应用提供基于任务的功能.服务可以被视为重复使用的执行一个或多个相关任务的代码块. AngularJS服务是单例对象, ...

  9. ThinkPHP中的内置标签

    ThinkPHP中的内置标签 1.内置标签分类 闭合标签 <tag></tag> 开放标签 <tag /> 2.包含文件标签 主要功能:实现对文件的包含(类似于re ...

随机推荐

  1. js Nullish Coalescing Operator

    js Nullish Coalescing Operator 空值合并 const n = null ?? 'default string'; console.log(n); // "def ...

  2. ESLint & vue

    ESLint & vue { "name": "app", "version": "1.0.1", " ...

  3. 微信小程序-导航 & 路由

    微信小程序-导航 & 路由 页面跳转 页面路由 页面栈, 框架以栈的形式维护了当前的所有页面. https://developers.weixin.qq.com/miniprogram/dev ...

  4. true && number !== boolean

    true && number !== boolean bug let result = ``; // section, name ? create text, compute cent ...

  5. HANNAH WHITE:不拖延的人生是什么样子的?

    不拖延的人生,究竟是什么样子呢?近日,星盟投资总经理HANNAH在一档人物采访栏目中表示,不拖延的人生,真的是太爽了! HANNAH在栏目中讲了一个曾经公司同事的故事.她说,那位同事总是喜欢拖延.每次 ...

  6. HDFS 02 - HDFS 的机制:副本机制、机架感知机制、负载均衡机制

    目录 1 - HDFS 的副本机制 2 - HDFS 的机架感知机制 3 - HDFS 的负载均衡机制 参考资料 版权声明 1 - HDFS 的副本机制 HDFS 中的文件,在物理上都是以分块(blo ...

  7. lms微服务框架介绍

    lms 框架简介 Lms是一个旨在通过.net平台快速构建微服务开发的框架.具有稳定.安全.高性能.易扩展.使用方便的特点.lms内部通过dotnetty实现高性能的rpc通信,使用zookeeper ...

  8. django学习-17.如何提供一个规范的接口返回值

    目录结构 1.前言 2.进行实际的一个完整流程操作 2.1.第一步:编写一个用于查询用户数据的视图函数 2.2.第二步:编写对应的一个url匹配规则 2.3.第三步:启动django项目[hellow ...

  9. hive分区分桶

    目录 1.分区 1.1.静态分区 1.1.1.一个分区 1.1.2.多个分区 1.2.动态分区 2.分桶 1.分区 如果一个表中数据很多,我们查询时就很慢,耗费大量时间,如果要查询其中部分数据该怎么办 ...

  10. 后端程序员之路 37、Akka、Actor、Scala初窥

    Akkahttp://akka.io/ Akka 是一个用 Scala 编写的库,用于简化编写容错的.高可伸缩性的 Java 和 Scala 的 Actor 模型应用,是一个广泛运用的分布式应用框架. ...