mirror of https://github.com/rust-lang/book
185 lines
9.0 KiB
Markdown
185 lines
9.0 KiB
Markdown
|
<!-- DO NOT EDIT THIS FILE.
|
|||
|
|
|||
|
This file is periodically generated from the content in the `/src/`
|
|||
|
directory, so all fixes need to be made in `/src/`.
|
|||
|
-->
|
|||
|
|
|||
|
[TOC]
|
|||
|
|
|||
|
## Appendix C: Derivable Traits
|
|||
|
|
|||
|
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.
|
|||
|
|
|||
|
In this appendix, we provide a reference of all the traits in the standard
|
|||
|
library that you can use with `derive`. Each section covers:
|
|||
|
|
|||
|
* What operators and methods deriving this trait will enable
|
|||
|
* What the implementation of the trait provided by `derive` does
|
|||
|
* What implementing the trait signifies about the type
|
|||
|
* The conditions in which you’re allowed or not allowed to implement the trait
|
|||
|
* Examples of operations that require the 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.
|
|||
|
|
|||
|
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.
|
|||
|
|
|||
|
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.
|
|||
|
|
|||
|
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 “Macros” on page XX.
|
|||
|
|
|||
|
## Debug for Programmer Output
|
|||
|
|
|||
|
The `Debug` trait enables debug formatting in format strings, which you
|
|||
|
indicate by adding `:?` within `{}` placeholders.
|
|||
|
|
|||
|
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.
|
|||
|
|
|||
|
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 programmers can see why the two instances weren’t
|
|||
|
equal.
|
|||
|
|
|||
|
## PartialEq and Eq for Equality Comparisons
|
|||
|
|
|||
|
The `PartialEq` trait allows you to compare instances of a type to check for
|
|||
|
equality and enables use of the `==` and `!=` operators.
|
|||
|
|
|||
|
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.
|
|||
|
|
|||
|
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.
|
|||
|
|
|||
|
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.
|
|||
|
|
|||
|
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.
|
|||
|
|
|||
|
## PartialOrd and Ord for Ordering Comparisons
|
|||
|
|
|||
|
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`.
|
|||
|
|
|||
|
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 not-a-number (`NaN`) floating
|
|||
|
point value. Calling `partial_cmp` with any floating-point number and the `NaN`
|
|||
|
floating-point value will return `None`.
|
|||
|
|
|||
|
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.
|
|||
|
|
|||
|
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.
|
|||
|
|
|||
|
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`.
|
|||
|
|
|||
|
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.
|
|||
|
|
|||
|
## Clone and Copy for Duplicating Values
|
|||
|
|
|||
|
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 “Variables and Data Interacting with Clone” on page XX for more
|
|||
|
information on `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`.
|
|||
|
|
|||
|
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`.
|
|||
|
|
|||
|
The `Copy` trait allows you to duplicate a value by only copying bits stored on
|
|||
|
the stack; no arbitrary code is necessary. See “Stack-Only Data: Copy” on page
|
|||
|
XX for more information on `Copy`.
|
|||
|
|
|||
|
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.
|
|||
|
|
|||
|
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`.
|
|||
|
|
|||
|
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.
|
|||
|
|
|||
|
Everything possible with `Copy` you can also accomplish with `Clone`, but the
|
|||
|
code might be slower or have to use `clone` in places.
|
|||
|
|
|||
|
## Hash for Mapping a Value to a Value of Fixed Size
|
|||
|
|
|||
|
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`.
|
|||
|
|
|||
|
An example of when `Hash` is required is in storing keys in a `HashMap<K, V>`
|
|||
|
to store data efficiently.
|
|||
|
|
|||
|
## Default for Default Values
|
|||
|
|
|||
|
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`.
|
|||
|
|
|||
|
The `Default::default` function is commonly used in combination with the struct
|
|||
|
update syntax discussed in “Creating Instances from Other Instances with Struct
|
|||
|
Update Syntax” on page XX. 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()`.
|
|||
|
|
|||
|
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>`.
|
|||
|
|