]> git.proxmox.com Git - rustc.git/blame - src/doc/book/src/ch10-02-traits.md
New upstream version 1.63.0+dfsg1
[rustc.git] / src / doc / book / src / ch10-02-traits.md
CommitLineData
13cf67c4
XL
1## Traits: Defining Shared Behavior
2
5e7ed085
FG
3A *trait* defines functionality a particular type has and can share with other
4types. We can use traits to define shared behavior in an abstract way. We can
5use *trait bounds* to specify that a generic type can be any type that has
6certain behavior.
13cf67c4
XL
7
8> Note: Traits are similar to a feature often called *interfaces* in other
9> languages, although with some differences.
10
11### Defining a Trait
12
13A type’s behavior consists of the methods we can call on that type. Different
14types share the same behavior if we can call the same methods on all of those
15types. Trait definitions are a way to group method signatures together to
16define a set of behaviors necessary to accomplish some purpose.
17
18For example, let’s say we have multiple structs that hold various kinds and
19amounts of text: a `NewsArticle` struct that holds a news story filed in a
20particular location and a `Tweet` that can have at most 280 characters along
21with metadata that indicates whether it was a new tweet, a retweet, or a reply
22to another tweet.
23
3c0e092e
XL
24We want to make a media aggregator library crate named `aggregator` that can
25display summaries of data that might be stored in a `NewsArticle` or `Tweet`
26instance. To do this, we need a summary from each type, and we’ll request
27that summary by calling a `summarize` method on an instance. Listing 10-12
28shows the definition of a public `Summary` trait that expresses this behavior.
13cf67c4
XL
29
30<span class="filename">Filename: src/lib.rs</span>
31
5869c6ff 32```rust,noplayground
74b04a01 33{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-12/src/lib.rs}}
13cf67c4
XL
34```
35
36<span class="caption">Listing 10-12: A `Summary` trait that consists of the
37behavior provided by a `summarize` method</span>
38
39Here, we declare a trait using the `trait` keyword and then the trait’s name,
3c0e092e
XL
40which is `Summary` in this case. We’ve also declared the trait as `pub` so that
41crates depending on this crate can make use of this trait too, as we’ll see in
42a few examples. Inside the curly brackets, we declare the method signatures
43that describe the behaviors of the types that implement this trait, which in
44this case is `fn summarize(&self) -> String`.
13cf67c4
XL
45
46After the method signature, instead of providing an implementation within curly
47brackets, we use a semicolon. Each type implementing this trait must provide
48its own custom behavior for the body of the method. The compiler will enforce
49that any type that has the `Summary` trait will have the method `summarize`
50defined with this signature exactly.
51
52A trait can have multiple methods in its body: the method signatures are listed
53one per line and each line ends in a semicolon.
54
55### Implementing a Trait on a Type
56
3c0e092e
XL
57Now that we’ve defined the desired signatures of the `Summary` trait’s methods,
58we can implement it on the types in our media aggregator. Listing 10-13 shows
59an implementation of the `Summary` trait on the `NewsArticle` struct that uses
60the headline, the author, and the location to create the return value of
13cf67c4
XL
61`summarize`. For the `Tweet` struct, we define `summarize` as the username
62followed by the entire text of the tweet, assuming that tweet content is
63already limited to 280 characters.
64
65<span class="filename">Filename: src/lib.rs</span>
66
5869c6ff 67```rust,noplayground
74b04a01 68{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-13/src/lib.rs:here}}
13cf67c4
XL
69```
70
71<span class="caption">Listing 10-13: Implementing the `Summary` trait on the
72`NewsArticle` and `Tweet` types</span>
73
74Implementing a trait on a type is similar to implementing regular methods. The
5e7ed085
FG
75difference is that after `impl`, we put the trait name we want to implement,
76then use the `for` keyword, and then specify the name of the type we want to
77implement the trait for. Within the `impl` block, we put the method signatures
78that the trait definition has defined. Instead of adding a semicolon after each
79signature, we use curly brackets and fill in the method body with the specific
80behavior that we want the methods of the trait to have for the particular type.
13cf67c4 81
3c0e092e
XL
82Now that the library has implemented the `Summary` trait on `NewsArticle` and
83`Tweet`, users of the crate can call the trait methods on instances of
84`NewsArticle` and `Tweet` in the same way we call regular methods. The only
5e7ed085
FG
85difference is that the user must bring the trait into scope as well as the
86types. Here’s an example of how a binary crate could use our `aggregator`
87library crate:
13cf67c4
XL
88
89```rust,ignore
3c0e092e 90{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/src/main.rs}}
13cf67c4
XL
91```
92
93This code prints `1 new tweet: horse_ebooks: of course, as you probably already
94know, people`.
95
3c0e092e 96Other crates that depend on the `aggregator` crate can also bring the `Summary`
5e7ed085
FG
97trait into scope to implement `Summary` on their own types. One restriction to
98note is that we can implement a trait on a type only if at least one of the
99trait or the type is local to our crate. For example, we can implement standard
100library traits like `Display` on a custom type like `Tweet` as part of our
101`aggregator` crate functionality, because the type `Tweet` is local to our
102`aggregator` crate. We can also implement `Summary` on `Vec<T>` in our
103`aggregator` crate, because the trait `Summary` is local to our `aggregator`
104crate.
13cf67c4
XL
105
106But we can’t implement external traits on external types. For example, we can’t
107implement the `Display` trait on `Vec<T>` within our `aggregator` crate,
5e7ed085
FG
108because `Display` and `Vec<T>` are both defined in the standard library and
109aren’t local to our `aggregator` crate. This restriction is part of a property
110called *coherence*, and more specifically the *orphan rule*, so named because
111the parent type is not present. This rule ensures that other people’s code
112can’t break your code and vice versa. Without the rule, two crates could
13cf67c4
XL
113implement the same trait for the same type, and Rust wouldn’t know which
114implementation to use.
115
116### Default Implementations
117
118Sometimes it’s useful to have default behavior for some or all of the methods
119in a trait instead of requiring implementations for all methods on every type.
120Then, as we implement the trait on a particular type, we can keep or override
121each method’s default behavior.
122
5e7ed085
FG
123In Listing 10-14 we specify a default string for the `summarize` method of the
124`Summary` trait instead of only defining the method signature, as we did in
125Listing 10-12.
13cf67c4
XL
126
127<span class="filename">Filename: src/lib.rs</span>
128
5869c6ff 129```rust,noplayground
74b04a01 130{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-14/src/lib.rs:here}}
13cf67c4
XL
131```
132
5e7ed085
FG
133<span class="caption">Listing 10-14: Defining a `Summary` trait with a default
134implementation of the `summarize` method</span>
13cf67c4 135
5e7ed085
FG
136To use a default implementation to summarize instances of `NewsArticle`, we
137specify an empty `impl` block with `impl Summary for NewsArticle {}`.
13cf67c4
XL
138
139Even though we’re no longer defining the `summarize` method on `NewsArticle`
140directly, we’ve provided a default implementation and specified that
141`NewsArticle` implements the `Summary` trait. As a result, we can still call
142the `summarize` method on an instance of `NewsArticle`, like this:
143
144```rust,ignore
74b04a01 145{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-02-calling-default-impl/src/main.rs:here}}
13cf67c4
XL
146```
147
148This code prints `New article available! (Read more...)`.
149
5e7ed085
FG
150Creating a default implementation doesn’t require us to change anything about
151the implementation of `Summary` on `Tweet` in Listing 10-13. The reason is that
152the syntax for overriding a default implementation is the same as the syntax
153for implementing a trait method that doesn’t have a default implementation.
13cf67c4
XL
154
155Default implementations can call other methods in the same trait, even if those
156other methods don’t have a default implementation. In this way, a trait can
157provide a lot of useful functionality and only require implementors to specify
158a small part of it. For example, we could define the `Summary` trait to have a
159`summarize_author` method whose implementation is required, and then define a
160`summarize` method that has a default implementation that calls the
161`summarize_author` method:
162
5869c6ff 163```rust,noplayground
74b04a01 164{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/src/lib.rs:here}}
13cf67c4
XL
165```
166
167To use this version of `Summary`, we only need to define `summarize_author`
168when we implement the trait on a type:
169
170```rust,ignore
74b04a01 171{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/src/lib.rs:impl}}
13cf67c4
XL
172```
173
174After we define `summarize_author`, we can call `summarize` on instances of the
175`Tweet` struct, and the default implementation of `summarize` will call the
176definition of `summarize_author` that we’ve provided. Because we’ve implemented
177`summarize_author`, the `Summary` trait has given us the behavior of the
178`summarize` method without requiring us to write any more code.
179
180```rust,ignore
74b04a01 181{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/src/main.rs:here}}
13cf67c4
XL
182```
183
184This code prints `1 new tweet: (Read more from @horse_ebooks...)`.
185
186Note that it isn’t possible to call the default implementation from an
187overriding implementation of that same method.
188
9fa01778 189### Traits as Parameters
13cf67c4 190
532ac7d7 191Now that you know how to define and implement traits, we can explore how to use
5e7ed085
FG
192traits to define functions that accept many different types. We'll use the
193`Summary` trait we implemented on the `NewsArticle` and `Tweet` types in
194Listing 10-13 to define a `notify` function that calls the `summarize` method
195on its `item` parameter, which is of some type that implements the `Summary`
196trait. To do this, we use the `impl Trait` syntax, like this:
13cf67c4
XL
197
198```rust,ignore
74b04a01 199{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-04-traits-as-parameters/src/lib.rs:here}}
13cf67c4
XL
200```
201
9fa01778 202Instead of a concrete type for the `item` parameter, we specify the `impl`
532ac7d7
XL
203keyword and the trait name. This parameter accepts any type that implements the
204specified trait. In the body of `notify`, we can call any methods on `item`
205that come from the `Summary` trait, such as `summarize`. We can call `notify`
206and pass in any instance of `NewsArticle` or `Tweet`. Code that calls the
207function with any other type, such as a `String` or an `i32`, won’t compile
208because those types don’t implement `Summary`.
13cf67c4 209
923072b8
FG
210<!-- Old headings. Do not remove or links may break. -->
211<a id="fixing-the-largest-function-with-trait-bounds"></a>
212
9fa01778 213#### Trait Bound Syntax
13cf67c4 214
5e7ed085
FG
215The `impl Trait` syntax works for straightforward cases but is actually syntax
216sugar for a longer form known as a *trait bound*; it looks like this:
13cf67c4
XL
217
218```rust,ignore
ba9703b0 219pub fn notify<T: Summary>(item: &T) {
13cf67c4
XL
220 println!("Breaking news! {}", item.summarize());
221}
222```
223
532ac7d7
XL
224This longer form is equivalent to the example in the previous section but is
225more verbose. We place trait bounds with the declaration of the generic type
226parameter after a colon and inside angle brackets.
13cf67c4 227
532ac7d7 228The `impl Trait` syntax is convenient and makes for more concise code in simple
5e7ed085
FG
229cases, while the fuller trait bound syntax can express more complexity in other
230cases. For example, we can have two parameters that implement `Summary`. Doing
231so with the `impl Trait` syntax looks like this:
13cf67c4
XL
232
233```rust,ignore
ba9703b0 234pub fn notify(item1: &impl Summary, item2: &impl Summary) {
13cf67c4
XL
235```
236
5e7ed085
FG
237Using `impl Trait` is appropriate if we want this function to allow `item1` and
238`item2` to have different types (as long as both types implement `Summary`). If
239we want to force both parameters to have the same type, however, we must use a
240trait bound, like this:
13cf67c4
XL
241
242```rust,ignore
ba9703b0 243pub fn notify<T: Summary>(item1: &T, item2: &T) {
13cf67c4
XL
244```
245
9fa01778
XL
246The generic type `T` specified as the type of the `item1` and `item2`
247parameters constrains the function such that the concrete type of the value
248passed as an argument for `item1` and `item2` must be the same.
13cf67c4 249
9fa01778
XL
250#### Specifying Multiple Trait Bounds with the `+` Syntax
251
532ac7d7 252We can also specify more than one trait bound. Say we wanted `notify` to use
5e7ed085
FG
253display formatting as well as `summarize` on `item`: we specify in the `notify`
254definition that `item` must implement both `Display` and `Summary`. We can do
255so using the `+` syntax:
13cf67c4
XL
256
257```rust,ignore
ba9703b0 258pub fn notify(item: &(impl Summary + Display)) {
13cf67c4
XL
259```
260
9fa01778 261The `+` syntax is also valid with trait bounds on generic types:
13cf67c4
XL
262
263```rust,ignore
ba9703b0 264pub fn notify<T: Summary + Display>(item: &T) {
13cf67c4
XL
265```
266
9fa01778
XL
267With the two trait bounds specified, the body of `notify` can call `summarize`
268and use `{}` to format `item`.
269
270#### Clearer Trait Bounds with `where` Clauses
13cf67c4 271
532ac7d7
XL
272Using too many trait bounds has its downsides. Each generic has its own trait
273bounds, so functions with multiple generic type parameters can contain lots of
274trait bound information between the function’s name and its parameter list,
9fa01778
XL
275making the function signature hard to read. For this reason, Rust has alternate
276syntax for specifying trait bounds inside a `where` clause after the function
277signature. So instead of writing this:
13cf67c4
XL
278
279```rust,ignore
ba9703b0 280fn some_function<T: Display + Clone, U: Clone + Debug>(t: &T, u: &U) -> i32 {
13cf67c4
XL
281```
282
283we can use a `where` clause, like this:
284
285```rust,ignore
ba9703b0 286fn some_function<T, U>(t: &T, u: &U) -> i32
13cf67c4
XL
287 where T: Display + Clone,
288 U: Clone + Debug
289{
290```
291
532ac7d7
XL
292This function’s signature is less cluttered: the function name, parameter list,
293and return type are close together, similar to a function without lots of trait
294bounds.
13cf67c4 295
9fa01778 296### Returning Types that Implement Traits
13cf67c4 297
532ac7d7
XL
298We can also use the `impl Trait` syntax in the return position to return a
299value of some type that implements a trait, as shown here:
13cf67c4
XL
300
301```rust,ignore
74b04a01 302{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-05-returning-impl-trait/src/lib.rs:here}}
13cf67c4
XL
303```
304
532ac7d7
XL
305By using `impl Summary` for the return type, we specify that the
306`returns_summarizable` function returns some type that implements the `Summary`
307trait without naming the concrete type. In this case, `returns_summarizable`
5e7ed085 308returns a `Tweet`, but the code calling this function doesn’t need to know that.
13cf67c4 309
5e7ed085
FG
310The ability to specify a return type only by the trait it implements is
311especially useful in the context of closures and iterators, which we cover in
312Chapter 13. Closures and iterators create types that only the compiler knows or
313types that are very long to specify. The `impl Trait` syntax lets you concisely
314specify that a function returns some type that implements the `Iterator` trait
315without needing to write out a very long type.
13cf67c4 316
532ac7d7
XL
317However, you can only use `impl Trait` if you’re returning a single type. For
318example, this code that returns either a `NewsArticle` or a `Tweet` with the
319return type specified as `impl Summary` wouldn’t work:
13cf67c4
XL
320
321```rust,ignore,does_not_compile
74b04a01 322{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-06-impl-trait-returns-one-type/src/lib.rs:here}}
13cf67c4
XL
323```
324
532ac7d7
XL
325Returning either a `NewsArticle` or a `Tweet` isn’t allowed due to restrictions
326around how the `impl Trait` syntax is implemented in the compiler. We’ll cover
327how to write a function with this behavior in the [“Using Trait Objects That
328Allow for Values of Different
9fa01778
XL
329Types”][using-trait-objects-that-allow-for-values-of-different-types]<!--
330ignore --> section of Chapter 17.
13cf67c4 331
13cf67c4
XL
332### Using Trait Bounds to Conditionally Implement Methods
333
334By using a trait bound with an `impl` block that uses generic type parameters,
335we can implement methods conditionally for types that implement the specified
923072b8 336traits. For example, the type `Pair<T>` in Listing 10-15 always implements the
3c0e092e 337`new` function to return a new instance of `Pair<T>` (recall from the
5e7ed085 338[“Defining Methods”][methods]<!-- ignore --> section of Chapter 5 that `Self`
3c0e092e
XL
339is a type alias for the type of the `impl` block, which in this case is
340`Pair<T>`). But in the next `impl` block, `Pair<T>` only implements the
341`cmp_display` method if its inner type `T` implements the `PartialOrd` trait
342that enables comparison *and* the `Display` trait that enables printing.
13cf67c4 343
74b04a01 344<span class="filename">Filename: src/lib.rs</span>
13cf67c4 345
5869c6ff 346```rust,noplayground
923072b8 347{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-15/src/lib.rs}}
13cf67c4
XL
348```
349
923072b8 350<span class="caption">Listing 10-15: Conditionally implementing methods on a
13cf67c4
XL
351generic type depending on trait bounds</span>
352
353We can also conditionally implement a trait for any type that implements
354another trait. Implementations of a trait on any type that satisfies the trait
355bounds are called *blanket implementations* and are extensively used in the
356Rust standard library. For example, the standard library implements the
357`ToString` trait on any type that implements the `Display` trait. The `impl`
358block in the standard library looks similar to this code:
359
360```rust,ignore
361impl<T: Display> ToString for T {
362 // --snip--
363}
364```
365
366Because the standard library has this blanket implementation, we can call the
367`to_string` method defined by the `ToString` trait on any type that implements
368the `Display` trait. For example, we can turn integers into their corresponding
369`String` values like this because integers implement `Display`:
370
371```rust
372let s = 3.to_string();
373```
374
375Blanket implementations appear in the documentation for the trait in the
376“Implementors” section.
377
378Traits and trait bounds let us write code that uses generic type parameters to
379reduce duplication but also specify to the compiler that we want the generic
380type to have particular behavior. The compiler can then use the trait bound
381information to check that all the concrete types used with our code provide the
382correct behavior. In dynamically typed languages, we would get an error at
ba9703b0
XL
383runtime if we called a method on a type which didn’t define the method. But Rust
384moves these errors to compile time so we’re forced to fix the problems before
385our code is even able to run. Additionally, we don’t have to write code that
386checks for behavior at runtime because we’ve already checked at compile time.
387Doing so improves performance without having to give up the flexibility of
388generics.
13cf67c4 389
5e7ed085 390[using-trait-objects-that-allow-for-values-of-different-types]: ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types
3c0e092e 391[methods]: ch05-03-method-syntax.html#defining-methods