mirror of
https://github.com/google/comprehensive-rust.git
synced 2025-06-01 15:19:35 +02:00
Expand Traits, add associated types (#1815)
This breaks the "Traits" slide into three smaller sub-slides. It also addresses part of #1511 by explicitly addressing associated types. --------- Co-authored-by: Martin Geisler <martin@geisler.net>
This commit is contained in:
parent
9d63f23f1d
commit
95fce416ce
@ -80,6 +80,8 @@
|
|||||||
- [Methods and Traits](methods-and-traits.md)
|
- [Methods and Traits](methods-and-traits.md)
|
||||||
- [Methods](methods-and-traits/methods.md)
|
- [Methods](methods-and-traits/methods.md)
|
||||||
- [Traits](methods-and-traits/traits.md)
|
- [Traits](methods-and-traits/traits.md)
|
||||||
|
- [Implmementing Traits](methods-and-traits/traits/implementing.md)
|
||||||
|
- [Associated Types](methods-and-traits/traits/associated-types.md)
|
||||||
- [Deriving](methods-and-traits/deriving.md)
|
- [Deriving](methods-and-traits/deriving.md)
|
||||||
- [Exercise: Generic Logger](methods-and-traits/exercise.md)
|
- [Exercise: Generic Logger](methods-and-traits/exercise.md)
|
||||||
- [Solution](methods-and-traits/solution.md)
|
- [Solution](methods-and-traits/solution.md)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
minutes: 8
|
minutes: 10
|
||||||
---
|
---
|
||||||
|
|
||||||
# Traits
|
# Traits
|
||||||
@ -7,40 +7,12 @@ minutes: 8
|
|||||||
Rust lets you abstract over types with traits. They're similar to interfaces:
|
Rust lets you abstract over types with traits. They're similar to interfaces:
|
||||||
|
|
||||||
```rust,editable
|
```rust,editable
|
||||||
struct Dog {
|
|
||||||
name: String,
|
|
||||||
age: i8,
|
|
||||||
}
|
|
||||||
struct Cat {
|
|
||||||
lives: i8,
|
|
||||||
}
|
|
||||||
|
|
||||||
trait Pet {
|
trait Pet {
|
||||||
|
/// Return a sentence from this pet.
|
||||||
fn talk(&self) -> String;
|
fn talk(&self) -> String;
|
||||||
|
|
||||||
fn greet(&self) {
|
/// Print a string to the terminal greeting this pet.
|
||||||
println!("Oh you're a cutie! What's your name? {}", self.talk());
|
fn greet(&self);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Pet for Dog {
|
|
||||||
fn talk(&self) -> String {
|
|
||||||
format!("Woof, my name is {}!", self.name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Pet for Cat {
|
|
||||||
fn talk(&self) -> String {
|
|
||||||
String::from("Miau!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let captain_floof = Cat { lives: 9 };
|
|
||||||
let fido = Dog { name: String::from("Fido"), age: 5 };
|
|
||||||
|
|
||||||
captain_floof.greet();
|
|
||||||
fido.greet();
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -49,10 +21,7 @@ fn main() {
|
|||||||
- A trait defines a number of methods that types must have in order to implement
|
- A trait defines a number of methods that types must have in order to implement
|
||||||
the trait.
|
the trait.
|
||||||
|
|
||||||
- Traits are implemented in an `impl <trait> for <type> { .. }` block.
|
- In the "Generics" segment, next, we will see how to build functionality that
|
||||||
|
is generic over all types implementing a trait.
|
||||||
- Traits may specify pre-implemented (provided) methods and methods that users
|
|
||||||
are required to implement themselves. Provided methods can rely on required
|
|
||||||
methods. In this case, `greet` is provided, and relies on `talk`.
|
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
37
src/methods-and-traits/traits/associated-types.md
Normal file
37
src/methods-and-traits/traits/associated-types.md
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# Associated Types
|
||||||
|
|
||||||
|
Associated types allow are placeholder types which are filled in by the trait
|
||||||
|
implementation.
|
||||||
|
|
||||||
|
```rust,editable
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Meters(i32);
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct MetersSquared(i32);
|
||||||
|
|
||||||
|
trait Multiply {
|
||||||
|
type Output;
|
||||||
|
fn multiply(&self, other: &Self) -> Self::Output;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Multiply for Meters {
|
||||||
|
type Output = MetersSquared;
|
||||||
|
fn multiply(&self, other: &Self) -> Self::Output {
|
||||||
|
MetersSquared(self.0 * other.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("{:?}", Meters(10).multiply(&Meters(20)));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
<details>
|
||||||
|
|
||||||
|
- Associated types are sometimes also called "output types". The key observation
|
||||||
|
is that the implementer, not the caller, chooses this type.
|
||||||
|
|
||||||
|
- Many standard library traits have associated types, including arithmetic
|
||||||
|
operators and `Iterator`.
|
||||||
|
|
||||||
|
</details>
|
42
src/methods-and-traits/traits/implementing.md
Normal file
42
src/methods-and-traits/traits/implementing.md
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# Implementing Traits
|
||||||
|
|
||||||
|
```rust,editable
|
||||||
|
trait Pet {
|
||||||
|
fn talk(&self) -> String;
|
||||||
|
|
||||||
|
fn greet(&self) {
|
||||||
|
println!("Oh you're a cutie! What's your name? {}", self.talk());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Dog {
|
||||||
|
name: String,
|
||||||
|
age: i8,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Pet for Dog {
|
||||||
|
fn talk(&self) -> String {
|
||||||
|
format!("Woof, my name is {}!", self.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let fido = Dog { name: String::from("Fido"), age: 5 };
|
||||||
|
fido.greet();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
<details>
|
||||||
|
|
||||||
|
- To implement `Trait` for `Type`, you use an `impl Trait for Type { .. }`
|
||||||
|
block.
|
||||||
|
|
||||||
|
- Unlike Go interfaces, just having matching methods is not enough: a `Cat` type
|
||||||
|
with a `talk()` method would not automatically satisfy `Pet` unless it is in
|
||||||
|
an `impl Pet` block.
|
||||||
|
|
||||||
|
- Traits may provide default implementations of some methods. Default
|
||||||
|
implementations can rely on all the methods of the trait. In this case,
|
||||||
|
`greet` is provided, and relies on `talk`.
|
||||||
|
|
||||||
|
</details>
|
Loading…
x
Reference in New Issue
Block a user