Skip to content

Commit ec73fc3

Browse files
authored
Merge pull request #1249 from adamchalmers/master
Fix #1053: Added a page about the dyn keyword
2 parents a72e9d2 + 37a2861 commit ec73fc3

File tree

2 files changed

+48
-0
lines changed

2 files changed

+48
-0
lines changed

src/SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@
133133

134134
- [Traits](trait.md)
135135
- [Derive](trait/derive.md)
136+
- [Returning Traits with `dyn`](trait/dyn.md)
136137
- [Operator Overloading](trait/ops.md)
137138
- [Drop](trait/drop.md)
138139
- [Iterators](trait/iter.md)

src/trait/dyn.md

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Returning Traits with `dyn`
2+
3+
The Rust compiler needs to know how much space every function's return type requires. This means all your functions have to return a concrete type. Unlike other languages, if you have a trait like `Animal`, you can't write a function that returns `Animal`, because its different implementations will need different amounts of memory.
4+
5+
However, there's an easy workaround. Instead of returning a trait object directly, our functions return a `Box` which _contains_ some `Animal`. A `box` is just a reference to some memory in the heap. Because a reference has a statically-known size, and the compiler can guarantee it points to a heap-allocated `Animal`, we can return a trait from our function!
6+
7+
Rust tries to be as explicit as possible whenever it allocates memory on the heap. So if your function returns a pointer-to-trait-on-heap in this way, you need to write the return type with the `dyn` keyword, e.g. `Box<dyn Animal>`.
8+
9+
```rust,editable
10+
struct Sheep {}
11+
struct Cow {}
12+
13+
trait Animal {
14+
// Instance method signature
15+
fn noise(&self) -> &'static str;
16+
}
17+
18+
// Implement the `Animal` trait for `Sheep`.
19+
impl Animal for Sheep {
20+
fn noise(&self) -> &'static str {
21+
"baaaaah!"
22+
}
23+
}
24+
25+
// Implement the `Animal` trait for `Cow`.
26+
impl Animal for Cow {
27+
fn noise(&self) -> &'static str {
28+
"moooooo!"
29+
}
30+
}
31+
32+
// Returns some struct that implements Animal, but we don't know which one at compile time.
33+
fn random_animal(random_number: f64) -> Box<dyn Animal> {
34+
if random_number < 0.5 {
35+
Box::new(Sheep {})
36+
} else {
37+
Box::new(Cow {})
38+
}
39+
}
40+
41+
fn main() {
42+
let random_number = 0.234;
43+
let animal = random_animal(random_number);
44+
println!("You've randomly chosen an animal, and it says {}", animal.noise());
45+
}
46+
47+
```

0 commit comments

Comments
 (0)