Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help


x-i18n: generated_at: “2026-03-01T09:12:27Z” model: gemini-3-flash-preview provider: google-gemini-cli source_hash: 5ea4664c1cda3c660cf77a247296c730f0d4e3734d702c0f02726cd690474d8e source_path: appendix-03-derivable-traits.md workflow: 16

附录 C:可派生的 Traits (Appendix C: Derivable Traits)

Appendix C: Derivable Traits

在本书的多个地方,我们讨论了 derive 属性,你可以将其应用于结构体或枚举定义。derive 属性生成的代码将会在你使用 derive 语法标注的类型上实现一个带有自身默认实现的 trait。

In various places in the book, we’ve discussed the derive attribute, which you can apply to a struct or enum definition. The derive attribute generates code that will implement a trait with its own default implementation on the type you’ve annotated with the derive syntax.

在本附录中,我们提供了标准库中所有可以与 derive 一起使用的 trait 的参考。每个部分涵盖:

In this appendix, we provide a reference of all the traits in the standard library that you can use with derive. Each section covers:

  • 派生此 trait 将启用哪些运算符和方法
  • What operators and methods deriving this trait will enable
  • derive 提供的 trait 实现做了什么
  • What the implementation of the trait provided by derive does
  • 实现该 trait 对类型意味着什么
  • What implementing the trait signifies about the type
  • 允许或不允许实现该 trait 的条件
  • The conditions in which you’re allowed or not allowed to implement the trait
  • 需要该 trait 的操作示例
  • Examples of operations that require the trait

如果你想要不同于 derive 属性所提供的行为,请查阅标准库文档中关于每个 trait 的详细信息,以了解如何手动实现它们。

If you want different behavior from that provided by the derive attribute, consult the standard library documentation for each trait for details on how to manually implement them.

这里列出的 trait 是标准库定义的唯一可以使用 derive 在你的类型上实现的 trait。标准库中定义的其他 trait 没有合理的默认行为,因此由你决定以符合你目标的方式来实现它们。

The traits listed here are the only ones defined by the standard library that can be implemented on your types using derive. Other traits defined in the standard library don’t have sensible default behavior, so it’s up to you to implement them in the way that makes sense for what you’re trying to accomplish.

一个不能派生的 trait 示例是 Display,它处理面向最终用户的格式化。你应该始终考虑向最终用户显示类型的适当方式。最终用户应该被允许看到类型的哪些部分?哪些部分是他们认为相关的?什么样的数据格式对他们来说最相关?Rust 编译器没有这些见解,因此它无法为你提供适当的默认行为。

An example of a trait that can’t be derived is Display, which handles formatting for end users. You should always consider the appropriate way to display a type to an end user. What parts of the type should an end user be allowed to see? What parts would they find relevant? What format of the data would be most relevant to them? The Rust compiler doesn’t have this insight, so it can’t provide appropriate default behavior for you.

本附录中提供的可派生 trait 列表并不全面:库可以为它们自己的 trait 实现 derive,这使得你可以使用 derive 的 trait 列表实际上是无限开放的。实现 derive 涉及到使用过程宏,这在第 20 章的“自定义 derive 宏”部分有详细介绍。

The list of derivable traits provided in this appendix is not comprehensive: Libraries can implement derive for their own traits, making the list of traits you can use derive with truly open ended. Implementing derive involves using a procedural macro, which is covered in the “Custom derive Macros” section in Chapter 20.

用于程序员输出的 Debug (Debug for Programmer Output)

Debug for Programmer Output

Debug trait 在格式化字符串中启用调试格式,你可以通过在 {} 占位符中添加 :? 来表示。

The Debug trait enables debug formatting in format strings, which you indicate by adding :? within {} placeholders.

Debug trait 允许你出于调试目的打印类型的实例,这样你和使用你的类型的其他程序员就可以在程序执行的特定点检查实例。

The Debug trait allows you to print instances of a type for debugging purposes, so you and other programmers using your type can inspect an instance at a particular point in a program’s execution.

例如,在使用 assert_eq! 宏时需要 Debug trait。如果相等断言失败,该宏会打印作为参数给出的实例的值,以便程序员看到为什么这两个实例不相等。

The Debug trait is required, for example, in the use of the assert_eq! macro. This macro prints the values of instances given as arguments if the equality assertion fails so that programmers can see why the two instances weren’t equal.

用于相等比较的 PartialEqEq (PartialEq and Eq for Equality Comparisons)

PartialEq and Eq for Equality Comparisons

PartialEq trait 允许你比较一个类型的实例以检查是否相等,并启用 ==!= 运算符的使用。

The PartialEq trait allows you to compare instances of a type to check for equality and enables use of the == and != operators.

派生 PartialEq 会实现 eq 方法。当在结构体上派生 PartialEq 时,只有当所有字段都相等时,两个实例才相等;如果任何字段不相等,则实例不相等。当在枚举上派生时,每个变体都与其自身相等,而与其他变体不相等。

Deriving PartialEq implements the eq method. When PartialEq is derived on structs, two instances are equal only if all fields are equal, and the instances are not equal if any fields are not equal. When derived on enums, each variant is equal to itself and not equal to the other variants.

例如,在使用 assert_eq! 宏时需要 PartialEq trait,该宏需要能够比较一个类型的两个实例是否相等。

The PartialEq trait is required, for example, with the use of the assert_eq! macro, which needs to be able to compare two instances of a type for equality.

Eq trait 没有方法。它的目的是表明对于标注类型的每个值,该值都与其自身相等。Eq trait 只能应用于也实现了 PartialEq 的类型,尽管并非所有实现 PartialEq 的类型都能实现 Eq。一个例子是浮点数类型:浮点数的实现规定,非数字值 (NaN) 的两个实例彼此不相等。

The Eq trait has no methods. Its purpose is to signal that for every value of the annotated type, the value is equal to itself. The Eq trait can only be applied to types that also implement PartialEq, although not all types that implement PartialEq can implement Eq. One example of this is floating-point number types: The implementation of floating-point numbers states that two instances of the not-a-number (NaN) value are not equal to each other.

需要 Eq 的一个例子是 HashMap<K, V> 中的键,以便 HashMap<K, V> 可以判断两个键是否相同。

An example of when Eq is required is for keys in a HashMap<K, V> so that the HashMap<K, V> can tell whether two keys are the same.

用于顺序比较的 PartialOrdOrd (PartialOrd and Ord for Ordering Comparisons)

PartialOrd and Ord for Ordering Comparisons

PartialOrd trait 允许你出于排序目的比较一个类型的实例。实现了 PartialOrd 的类型可以与 <><=>= 运算符一起使用。你只能将 PartialOrd trait 应用于也实现了 PartialEq 的类型。

The PartialOrd trait allows you to compare instances of a type for sorting purposes. A type that implements PartialOrd can be used with the <, >, <=, and >= operators. You can only apply the PartialOrd trait to types that also implement PartialEq.

派生 PartialOrd 会实现 partial_cmp 方法,该方法返回一个 Option<Ordering>,当给定的值无法产生顺序时,它将是 None。一个尽管该类型的大多数值都可以比较,但无法产生顺序的值的例子是 NaN 浮点值。使用任何浮点数和 NaN 浮点值调用 partial_cmp 都会返回 None

Deriving PartialOrd implements the partial_cmp method, which returns an Option<Ordering> that will be None when the values given don’t produce an ordering. An example of a value that doesn’t produce an ordering, even though most values of that type can be compared, is the NaN floating point value. Calling partial_cmp with any floating-point number and the NaN floating-point value will return None.

当在结构体上派生时,PartialOrd 通过按字段在结构体定义中出现的顺序比较每个字段的值来比较两个实例。当在枚举上派生时,在枚举定义中较早声明的枚举变体被认为小于后面列出的变体。

When derived on structs, PartialOrd compares two instances by comparing the value in each field in the order in which the fields appear in the struct definition. When derived on enums, variants of the enum declared earlier in the enum definition are considered less than the variants listed later.

例如,rand crate 中的 gen_range 方法需要 PartialOrd trait,该方法在范围表达式指定的范围内生成随机值。

The PartialOrd trait is required, for example, for the gen_range method from the rand crate that generates a random value in the range specified by a range expression.

Ord trait 允许你知晓对于标注类型的任何两个值,都会存在有效的顺序。Ord trait 实现了 cmp 方法,它返回一个 Ordering 而不是 Option<Ordering>,因为有效的顺序总是有可能的。你只能将 Ord trait 应用于也实现了 PartialOrdEq 的类型(而 Eq 要求 PartialEq)。当在结构体和枚举上派生时,cmp 的行为与 PartialOrd 的派生实现对 partial_cmp 的行为相同。

The Ord trait allows you to know that for any two values of the annotated type, a valid ordering will exist. The Ord trait implements the cmp method, which returns an Ordering rather than an Option<Ordering> because a valid ordering will always be possible. You can only apply the Ord trait to types that also implement PartialOrd and Eq (and Eq requires PartialEq). When derived on structs and enums, cmp behaves the same way as the derived implementation for partial_cmp does with PartialOrd.

需要 Ord 的一个例子是在 BTreeSet<T> 中存储值时,这是一种基于值的排序顺序存储数据的数据结构。

An example of when Ord is required is when storing values in a BTreeSet<T>, a data structure that stores data based on the sort order of the values.

用于复制值的 CloneCopy (Clone and Copy for Duplicating Values)

Clone and Copy for Duplicating Values

Clone trait 允许你显式地创建一个值的深拷贝,复制过程可能涉及运行任意代码和复制堆上的数据。有关 Clone 的更多信息,请参阅第 4 章中的“变量与数据交互的方式:Clone”部分。

The Clone trait allows you to explicitly create a deep copy of a value, and the duplication process might involve running arbitrary code and copying heap data. See the “Variables and Data Interacting with Clone” section in Chapter 4 for more information on Clone.

派生 Clone 会实现 clone 方法,当为整个类型实现该方法时,它会对类型的每个部分调用 clone。这意味着要派生 Clone,类型中的所有字段或值也必须实现 Clone

Deriving Clone implements the clone method, which when implemented for the whole type, calls clone on each of the parts of the type. This means all the fields or values in the type must also implement Clone to derive Clone.

需要 Clone 的一个例子是在切片上调用 to_vec 方法时。切片并不拥有它所包含的类型实例,但从 to_vec 返回的 vector 将需要拥有它的实例,因此 to_vec 对每个项调用 clone。因此,存储在切片中的类型必须实现 Clone

An example of when Clone is required is when calling the to_vec method on a slice. The slice doesn’t own the type instances it contains, but the vector returned from to_vec will need to own its instances, so to_vec calls clone on each item. Thus, the type stored in the slice must implement Clone.

Copy trait 允许你仅通过复制存储在栈上的位来复制一个值;不需要运行任意代码。有关 Copy 的更多信息,请参阅第 4 章中的“只在栈上的数据:Copy”部分。

The Copy trait allows you to duplicate a value by only copying bits stored on the stack; no arbitrary code is necessary. See the “Stack-Only Data: Copy” section in Chapter 4 for more information on Copy.

Copy trait 没有定义任何方法,以防止程序员重载这些方法并违反不运行任意代码的假设。这样,所有程序员都可以假设复制一个值会非常快。

The Copy trait doesn’t define any methods to prevent programmers from overloading those methods and violating the assumption that no arbitrary code is being run. That way, all programmers can assume that copying a value will be very fast.

你可以在任何其各部分都实现了 Copy 的类型上派生 Copy。实现 Copy 的类型也必须实现 Clone,因为实现 Copy 的类型有一个简单的 Clone 实现,它执行与 Copy 相同的任务。

You can derive Copy on any type whose parts all implement Copy. A type that implements Copy must also implement Clone because a type that implements Copy has a trivial implementation of Clone that performs the same task as Copy.

Copy trait 很少被强制要求;实现 Copy 的类型可以使用优化,这意味着你不必调用 clone,这使代码更简洁。

The Copy trait is rarely required; types that implement Copy have optimizations available, meaning you don’t have to call clone, which makes the code more concise.

凡是可以通过 Copy 实现的,你也可以通过 Clone 来完成,但代码可能会变慢,或者必须在某些地方使用 clone

Everything possible with Copy you can also accomplish with Clone, but the code might be slower or have to use clone in places.

用于将值映射到固定大小值的 Hash (Hash for Mapping a Value to a Value of Fixed Size)

Hash for Mapping a Value to a Value of Fixed Size

Hash trait 允许你获取任意大小类型的实例,并使用哈希函数将该实例映射到固定大小的值。派生 Hash 会实现 hash 方法。hash 方法的派生实现结合了对类型的每个部分调用 hash 的结果,这意味着要派生 Hash,所有字段或值也必须实现 Hash

The Hash trait allows you to take an instance of a type of arbitrary size and map that instance to a value of fixed size using a hash function. Deriving Hash implements the hash method. The derived implementation of the hash method combines the result of calling hash on each of the parts of the type, meaning all fields or values must also implement Hash to derive Hash.

需要 Hash 的一个例子是在 HashMap<K, V> 中存储键,以便高效地存储数据。

An example of when Hash is required is in storing keys in a HashMap<K, V> to store data efficiently.

用于默认值的 Default (Default for Default Values)

Default for Default Values

Default trait 允许你为一个类型创建默认值。派生 Default 会实现 default 函数。default 函数的派生实现会对类型的每个部分调用 default 函数,这意味着要派生 Default,类型中的所有字段或值也必须实现 Default

The Default trait allows you to create a default value for a type. Deriving Default implements the default function. The derived implementation of the default function calls the default function on each part of the type, meaning all fields or values in the type must also implement Default to derive Default.

Default::default 函数通常与第 5 章“使用结构体更新语法从其他实例创建实例”部分讨论的结构体更新语法结合使用。你可以自定义结构体的几个字段,然后通过使用 ..Default::default() 为其余字段设置并使用默认值。

The Default::default function is commonly used in combination with the struct update syntax discussed in the “Creating Instances from Other Instances with Struct Update Syntax” section in Chapter 5. You can customize a few fields of a struct and then set and use a default value for the rest of the fields by using ..Default::default().

例如,当你对 Option<T> 实例使用 unwrap_or_default 方法时,就需要 Default trait。如果 Option<T>Noneunwrap_or_default 方法将返回存储在 Option<T> 中的类型 TDefault::default 的结果。

The Default trait is required when you use the method unwrap_or_default on Option<T> instances, for example. If the Option<T> is None, the method unwrap_or_default will return the result of Default::default for the type T stored in the Option<T>.