附录 C:可派生特征

在本书的不同地方,我们讨论了derive属性,其中 您可以应用于 struct 或 enum 定义。这derive属性生成 代码,该代码将在 键入derive语法。

在本附录中,我们提供了标准中所有特征的参考 库derive.每个部分都涵盖:

  • 派生此 trait 的运算符和方法将启用
  • trait 提供的实现是什么derivedoes
  • 实现 trait 对类型意味着什么
  • 允许或不允许您实施 trait 的条件
  • 需要 trait 的作示例

如果您希望的行为与derive属性 有关如何手动实施它们的详细信息,请参阅每个特征的标准库文档

此处列出的这些特征是标准库定义的唯一特征 可以使用derive.在 standard 库没有合理的默认行为,因此由您来 以对您要完成的任务有意义的方式实施它们。

无法派生的特征的一个示例是Display,它处理 面向最终用户的格式设置。您应该始终考虑适当的方式 向最终用户显示类型。最终用户应为类型的哪些部分 允许查看?他们认为哪些部分相关?数据的格式 对他们来说最相关吗?Rust 编译器没有这个洞察力,所以 它无法为您提供适当的默认行为。

本附录中提供的可衍生特征列表并不全面: 库可以实现derive对于他们自己的特征,将 您可以使用的特征derive与 TRULY 开放式。实施derive涉及使用过程宏,这在第 19 章的 “宏” 一节中介绍。

Debug用于编程器输出

Debugtrait 在格式字符串中启用调试格式,而 通过添加:?在占位符中。{}

Debugtrait 允许您打印某种类型的实例以进行调试 目的,以便您和其他使用您的类型的程序员可以检查实例 在程序执行的特定点。

Debugtrait 是必需的,例如,在使用assert_eq!宏。 如果相等 断言失败,因此程序员可以看到为什么这两个实例不相等。

PartialEqEqfor Equality Comparisons (相等比较)

PartialEqtrait 允许您比较要检查的类型的实例 相等,并允许使用 和==!=运营商。

推导PartialEq实现eq方法。什么时候PartialEq派生于 structs 中,只有当所有字段都相等时,两个实例才相等,并且 如果任何字段不相等,则实例不相等。当在枚举上派生时, 每个变体都等于自身,不等于其他变体。

PartialEqtrait 是必需的,例如,使用assert_eq!宏,它需要能够比较一个类型的两个实例 为了平等。

Eqtrait 没有方法。其目的是表示对于每个 的 annotated 类型,则值等于自身。这Eqtrait 只能是 应用于同时实现PartialEq,尽管并非所有类型 实现PartialEq可以实施Eq.这方面的一个例子是浮点 Number types:浮点数的实现表明两个 非数字 (NaN) 值不相等。

when 的示例Eq是必需的,用于HashMap<K, V>所以HashMap<K, V>可以判断两个 key 是否相同。

PartialOrdOrd用于排序比较

PartialOrdtrait 允许您比较类型的实例以进行排序 目的。实现PartialOrd可以与 、 、 和 运算符一起使用。您只能应用<><=>=PartialOrd类型的 trait 也实现PartialEq.

推导PartialOrd实现partial_cmp方法,该方法返回一个Option<Ordering>那将是None当给定的值不会产生 订购。一个不产生排序的值示例,即使 该类型的大多数值都可以比较,是非数字 (NaN) 浮动 点值。叫partial_cmp替换为任何浮点数和NaN浮点值将返回None.

当派生于 structs 时,PartialOrd通过比较 值 (value ) 中字段在结构体中出现的顺序 定义。当在枚举上派生时,之前在 enum 定义被视为小于后面列出的变体。

PartialOrdtrait 是必需的,例如,对于gen_range方法 从randcrate 生成一个随机值,范围由 range 表达式。

Ordtrait 允许您知道,对于带注释的 type,则存在有效的排序。这Ordtrait 实现cmp方法 ,它返回一个Ordering而不是Option<Ordering>因为有效的 订购总是可能的。您只能应用Ord类型的 trait 也实现PartialOrdEq(以及Eq需要PartialEq).什么时候 派生于结构和枚举,cmp的行为方式与派生的 implementation forpartial_cmpPartialOrd.

when 的示例Ord是必需的,当将值存储在BTreeSet<T>, 一种根据值的排序顺序存储数据的数据结构。

CloneCopy用于复制值

Clonetrait 允许您显式地创建值的深层副本,并且 复制过程可能涉及运行任意代码和复制堆 数据。请参阅“变量和数据交互的方式: Clone“ 部分 第 4 章 了解更多信息Clone.

推导Clone实现clone方法,当为 整个类型,调用clone在类型的每个部分上。这意味着所有 类型中的字段或值也必须实现Clone衍生Clone.

when 的示例Clone是必需的,在调用to_vec方法在 片。切片不拥有它包含的类型实例,而是 vector 返回自to_vec将需要拥有其实例,因此to_vec调用clone在每个项目上。因此,存储在 slice 中的类型必须实现Clone.

Copytrait 允许您通过仅复制存储在 堆栈;不需要任意代码。请参阅“仅堆栈数据: Copy“部分了解更多信息 信息Copy.

Copytrait 没有定义任何方法来防止程序员 重载这些方法并违反以下假设:没有任意代码 正在运行。这样,所有程序员都可以假设复制一个值将是 非常快。

您可以派生Copy在部分全部实现Copy.一种类型 实现Copy还必须实现Clone,因为实现Copy具有Clone执行与Copy.

Copy性状很少是必需的;实现Copy有 优化,这意味着您不必调用clone,这使得 代码更简洁。

一切皆有可能Copy您还可以使用Clone,但 代码可能更慢或必须使用clone在某些地方。

Hash用于将值映射到固定大小的值

Hashtrait 允许您获取任意大小的类型的实例,并且 使用哈希函数将该实例映射到 fixed size 的值。推导Hash实现hash方法。的hashmethod 合并调用hash在类型的每个部分上, 这意味着所有字段或值也必须实现Hash衍生Hash.

when 的示例Hash是必需的,用于将密钥存储在HashMap<K, V>以有效地存储数据。

Default对于默认值

Defaulttrait 允许您为类型创建默认值。推导Default实现default功能。的default函数调用default函数对类型的每个部分执行, 这意味着类型中的所有字段或值也必须实现Default自 获得Default.

Default::defaultfunction 通常与 struct 结合使用 update 语法在“从其他实例创建实例 结构体更新 Syntax“部分。您可以自定义结构体的几个字段,然后 使用..Default::default().

Defaulttrait 时需要unwrap_or_defaultOption<T>实例。如果Option<T>None、方法unwrap_or_default将返回Default::default对于类型T存储在Option<T>.

本文档由官方文档翻译而来,如有差异请以官方英文文档(https://doc.rust-lang.org/)为准