Edits to associated types

This commit is contained in:
Carol (Nichols || Goulding)
2018-01-02 15:40:00 -05:00
parent f7f5e4835c
commit 62ca2eeb44
2 changed files with 85 additions and 57 deletions

View File

@@ -1050,24 +1050,31 @@ Next, lets take a look at some other advanced features dealing with traits!
## Advanced Traits
We covered traits in Chapter 10, but like lifetimes, we didnt get to all the
details. Now that we know more Rust, we can get into the nitty-gritty.
We covered traits in Chapter 10 but, like lifetimes, we didnt get to some of
the more advanced details. Now that we know more Rust, we can get into the
nitty-gritty.
### Associated Types
### Associated Types Specify Placeholder Types in Trait Definitions
*Associated types* are a way of associating a type placeholder with a trait
such that the trait method definitions can use these placeholder types in their
signatures. The implementor of a trait will specify the concrete type to be
used in this types place for the particular implementation.
used in this types place for the particular implementation. That way, we can
define a trait that uses some types without needing to know exactly what those
types are until the trait is implemented.
Weve described most of the things in this chapter as being very rare.
Associated types are somewhere in the middle; theyre more rare than the rest
of the book, but more common than many of the things in this chapter.
<!-- Can you say what this is useful for -- it seems like a way to not to have
to specify a type prior to use, is that right? -->
<!-- Prior to trait implementation, yes. /Carol -->
An example of a trait with an associated type is the `Iterator` trait provided
by the standard library. It has an associated type named `Item` that stands in
for the type of the values that were iterating over. We mentioned in Chapter
13 that the definition of the `Iterator` trait is as shown in Listing 19-20:
Weve described most of the things in this chapter as being needed very rarely.
Associated types are somewhere in the middle; theyre used more rarely than the
rest of the book, but more commonly than many of the things in this chapter.
One example of a trait with an associated type is the `Iterator` trait provided
by the standard library. This has an associated type named `Item` that stands
in for the type of the values it's iterating over. We mentioned in Chapter 13
that the definition of the `Iterator` trait is as shown in Listing 19-20:
```
pub trait Iterator {
@@ -1079,16 +1086,20 @@ pub trait Iterator {
Listing 19-20: The definition of the `Iterator` trait that has an associated
type `Item`
This says that the `Iterator` trait has an associated type named `Item`. `Item`
is a placeholder type, and the return value of the `next` method will return
values of type `Option<Self::Item>`. Implementors of this trait will specify
the concrete type for `Item`, and the `next` method will return an `Option`
containing a value of whatever type the implementor has specified.
The `Iterator` trait has an associated type named `Item`. This is a placeholder
type, and the `next` method will return values of type `Option<Self::Item>`.
Implementors of this trait will specify the concrete type for `Item`, and the
`next` method will return an `Option` containing a value of that concrete type.
#### Associated Types Versus Generics
When we implemented the `Iterator` trait on the `Counter` struct in Listing
13-6, we specified that the `Item` type was `u32`:
This may seem like a similar concept to generics, in that it allows us to
define a function without specifying what types it can deal with. So why use
associated types?
Let's examine the difference with an example that implements the `Iterator`
trait on the `Counter` struct. In Listing 13-6, we specified that the `Item`
type was `u32`:
```
impl Iterator for Counter {
@@ -1097,8 +1108,8 @@ impl Iterator for Counter {
fn next(&mut self) -> Option<Self::Item> {
```
This feels similar to generics. So why isnt the `Iterator` trait defined as
shown in Listing 19-21?
This feels similar to generics. So why not just define the `Iterator` trait
with generics as shown in Listing 19-21?
```
pub trait Iterator<T> {
@@ -1108,17 +1119,18 @@ pub trait Iterator<T> {
Listing 19-21: A hypothetical definition of the `Iterator` trait using generics
The difference is that with the definition in Listing 19-21, we could also
implement `Iterator<String> for Counter`, or any other type as well, so that
wed have multiple implementations of `Iterator` for `Counter`. In other words,
when a trait has a generic parameter, we can implement that trait for a type
multiple times, changing the generic type parameters concrete types each time.
Then when we use the `next` method on `Counter`, wed have to provide type
The difference lies in the fact that when using generics like in Listing 19-21,
we have to annotate the types in each implementation. This is because we can
also implement `Iterator<String> for Counter`, or any other type, which would
give us multiple implementations of `Iterator` for `Counter`. In other words,
when a trait has a generic parameter, it can be implemented for a type multiple
times, changing the concrete types of the generic type parameters each time.
When we use the `next` method on `Counter`, wed then have to provide type
annotations to indicate which implementation of `Iterator` we wanted to use.
With associated types, we cant implement a trait on a type multiple times.
Using the actual definition of `Iterator` from Listing 19-20, we can only
choose once what the type of `Item` will be, since there can only be one `impl
With associated types, we don't need to annotate types because we cant
implement a trait on a type multiple times. With Listing 19-20, we can only
choose once what the type of `Item` will be, because there can only be one `impl
Iterator for Counter`. We dont have to specify that we want an iterator of
`u32` values everywhere that we call `next` on `Counter`.

View File

@@ -1,23 +1,31 @@
## Advanced Traits
We covered traits in Chapter 10, but like lifetimes, we didnt get to all the
We first covered traits in the “Traits: Defining Shared Behavior” section of
Chapter 10 but, like lifetimes, we didnt get to some of the more advanced
details. Now that we know more Rust, we can get into the nitty-gritty.
### Associated Types
### Associated Types Specify Placeholder Types in Trait Definitions
*Associated types* are a way of associating a type placeholder with a trait
such that the trait method definitions can use these placeholder types in their
signatures. The implementor of a trait will specify the concrete type to be
used in this types place for the particular implementation.
used in this types place for the particular implementation. That way, we can
define a trait that uses some types without needing to know exactly what those
types are until the trait is implemented.
Weve described most of the things in this chapter as being very rare.
Associated types are somewhere in the middle; theyre more rare than the rest
of the book, but more common than many of the things in this chapter.
<!-- Can you say what this is useful for -- it seems like a way to not to have
to specify a type prior to use, is that right? -->
<!-- Prior to trait implementation, yes. /Carol -->
An example of a trait with an associated type is the `Iterator` trait provided
by the standard library. It has an associated type named `Item` that stands in
for the type of the values that were iterating over. We mentioned in Chapter
13 that the definition of the `Iterator` trait is as shown in Listing 19-20:
Weve described most of the things in this chapter as being needed very rarely.
Associated types are somewhere in the middle; theyre used more rarely than the
rest of the book, but more commonly than many of the things in this chapter.
One example of a trait with an associated type is the `Iterator` trait provided
by the standard library. This has an associated type named `Item` that stands
in for the type of the values its iterating over. In “The `Iterator` Trait and
the `next` Method” section of Chapter 13, we mentioned that the definition of
the `Iterator` trait is as shown in Listing 19-20:
```rust
pub trait Iterator {
@@ -29,26 +37,33 @@ pub trait Iterator {
<span class="caption">Listing 19-20: The definition of the `Iterator` trait
that has an associated type `Item`</span>
This says that the `Iterator` trait has an associated type named `Item`. `Item`
is a placeholder type, and the return value of the `next` method will return
values of type `Option<Self::Item>`. Implementors of this trait will specify
the concrete type for `Item`, and the `next` method will return an `Option`
containing a value of whatever type the implementor has specified.
The `Iterator` trait has an associated type named `Item`. This is a placeholder
type, and the `next` method will return values of type `Option<Self::Item>`.
Implementors of this trait will specify the concrete type for `Item`, and the
`next` method will return an `Option` containing a value of that concrete type.
#### Associated Types Versus Generics
When we implemented the `Iterator` trait on the `Counter` struct in Listing
13-6, we specified that the `Item` type was `u32`:
This may seem like a similar concept to generics, in that it allows us to
define a function without specifying what types it can deal with. So why use
associated types?
Lets examine the difference with an example that implements the `Iterator`
trait on the `Counter` struct from Chapter 13. In Listing 13-21, we specified
that the `Item` type was `u32`:
<span class="filename">Filename: src/lib.rs</span>
```rust,ignore
impl Iterator for Counter {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
// --snip--
```
This feels similar to generics. So why isnt the `Iterator` trait defined as
shown in Listing 19-21?
This feels similar to generics. So why not just define the `Iterator` trait
with generics as shown in Listing 19-21?
```rust
pub trait Iterator<T> {
@@ -59,17 +74,18 @@ pub trait Iterator<T> {
<span class="caption">Listing 19-21: A hypothetical definition of the
`Iterator` trait using generics</span>
The difference is that with the definition in Listing 19-21, we could also
implement `Iterator<String> for Counter`, or any other type as well, so that
wed have multiple implementations of `Iterator` for `Counter`. In other words,
when a trait has a generic parameter, we can implement that trait for a type
multiple times, changing the generic type parameters concrete types each time.
Then when we use the `next` method on `Counter`, wed have to provide type
The difference lies in the fact that when using generics like in Listing 19-21,
we have to annotate the types in each implementation. This is because we can
also implement `Iterator<String> for Counter`, or any other type, which would
give us multiple implementations of `Iterator` for `Counter`. In other words,
when a trait has a generic parameter, it can be implemented for a type multiple
times, changing the concrete types of the generic type parameters each time.
When we use the `next` method on `Counter`, wed then have to provide type
annotations to indicate which implementation of `Iterator` we wanted to use.
With associated types, we cant implement a trait on a type multiple times.
Using the actual definition of `Iterator` from Listing 19-20, we can only
choose once what the type of `Item` will be, since there can only be one `impl
With associated types, we dont need to annotate types because we cant
implement a trait on a type multiple times. With Listing 19-20, we can only
choose once what the type of `Item` will be, because there can only be one `impl
Iterator for Counter`. We dont have to specify that we want an iterator of
`u32` values everywhere that we call `next` on `Counter`.