forked from richardanaya/tour_of_rust
-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathchapter_7.yaml
360 lines (246 loc) · 20.8 KB
/
chapter_7.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
- title: Chapter 7 - Object Oriented Programming
content_markdown: >
Expressing ideas with functions is a proven way of representing behavior and
data (C
has been doing it for decades!). Historically, computer science has found
other
useful expressive aggregations and abstractions for data. You may be
familiar with object oriented programming (OOP) as one
such way. In this chapter we'll explore the Rust programming language beyond
functions.
- title: What Is OOP?
content_markdown: >
Object oriented programming roughly refers to programming languages that
have a number of iconic features:
* Encapsulation - Associating data and functions into the conceptual unit of
a single type called an *object*.
* Abstraction - Hiding data and function members to obfuscate implementation
details of an object.
* Polymorphism - The ability to interact with objects of different types through
one interface.
* Inheritance - The ability to inherit data and behavior from other objects.
- title: Rust Is Not OOP
content_markdown: >
Rust lacks inheritance of data and behavior in any meaningful way.
* Structs cannot inherit fields from a parent struct.
* Structs cannot inherit functions from a parent struct.
That said, Rust implements many programming language features, so that you
might not mind this lacking.
- title: self and Self
code: >-
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&code=struct+Coordinates+%7B%0A++++x%3A+i32%2C%0A++++y%3A+i32%2C%0A%7D%0A%0Aimpl+Coordinates+%7B%0A++++%2F%2F+the+return+value%2C+Self%2C+has+the+data+type+as+the+implemented+struct+%0A++++%2F%2F+this+method+is+static%0A++++fn+new%28xval%3A+i32%2C+yval%3A+i32%29+-%3E+Self+%7B%0A++++++++return+Coordinates+%7B%0A++++++++++++x%3A+xval%2C%0A++++++++++++y%3A+yval%2C%0A++++++++%7D%0A++++%7D%0A++++%0A++++fn+setx%28%26mut+self%2C+xval%3A+i32%29+%7B%0A++++++++self.x+%3D+xval%3B%0A++++%7D%0A++++%0A++++fn+sety%28%26mut+self%2C+yval%3A+i32%29+%7B%0A++++++++self.y+%3D+yval%3B%0A++++%7D%0A++++%0A++++fn+disp%28%26self%29+%7B%0A++++++++println%21%28%22Point+located+at+%3A+%7B%7D+on+OX++%7B%7D+on+OY%22%2C%0A++++++++++++++++self.x%2C+self.y%29%3B%0A++++%7D%0A++++%0A%7D%0A%0Afn+main%28%29+%7B%0A++++let+mut+p+%3D+Coordinates%3A%3Anew%28-1i32%2C+1i32%29%3B%0A++++p.disp%28%29%3B%0A++++p.setx%2810++as+i32%29%3B%0A++++p.sety%28-10+as+i32%29%3B%0A++++p.disp%28%29%3B%0A%7D%0A
content_markdown: >
In Rust, `self` and `Self` are fundamental concepts in ownership and
borrowing system. Both of them are used in `impl` and `trait` blocks.
`self`:
- refers to an **instance of struct**
- reference to itself
- is the first parameter of the method
- methods containing the `self` parameter are called using the name of the instance, the operator `.` and the name of the method
`Self`:
- refers to **return type** of the method
- has the same data type as the `struct` that is implemented in a `impl` block
- can be used for static methods using the operator `::` (they do not depend on a instance of a struct or contain `self` as a parameter)
- title: Defining a macro
code: >-
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&code=struct+Coordinates+%7B%0A++++x%3A+i32%2C%0A++++y%3A+i32%2C%0A%7D%0A%0Aimpl+Coordinates+%7B%0A++++%2F%2F+original+copy+constructor%2C+a+static+method%0A++++fn+new%28xval%3A+i32%2C+yval%3A+i32%29+-%3E+Self+%7B%0A++++++++Coordinates+%7B+x%3A+xval%2C+y%3A+yval+%7D%0A++++%7D%0A%7D%0A%0Aimpl+Coordinates+%7B%0A++++fn+disp%28%26self%29+%7B%0A++++++++println%21%28%22Point+located+at%3A+%7B%7D+on+OX%2C+%7B%7D+on+OY%22%2C+self.x%2C+self.y%29%3B%0A++++%7D%0A%7D%0A%0A%2F%2F+the+coord%21+macro%0Amacro_rules%21+coord+%7B%0A++++%28%24x%3Aexpr%2C+%24y%3Aexpr%29+%3D%3E+%7B%0A++++++++Coordinates%3A%3Anew%28%24x%2C+%24y%29%0A++++%7D%3B%0A%7D%0A%0Afn+main%28%29+%7B%0A++++%2F%2F+Use+the+coord%21+macro+to+create+a+new+Coordinates+instance%0A++++let+p1%3A+Coordinates+%3D+coord%21%281%2C+2%29%3B%0A%0A++++%2F%2F+Alternatively%2C+you+can+use+the+coord%21+macro+with+square+brackets%0A++++let+p2+%3D+coord%21%5B2%2C+2%5D%3B%0A++++%0A++++let+p3+%3D+Coordinates+%7B%0A++++++++x%3A+10i32%2C%0A++++++++y%3A+11+as+i32%2C%0A++++%7D%3B%0A++++%0A++++let+p4+%3D+Coordinates%3A%3Anew%28-10%2C+11%29%3B%0A%0A++++p1.disp%28%29%3B%0A++++p2.disp%28%29%3B%0A++++p3.disp%28%29%3B%0A++++p4.disp%28%29%3B%0A%7D%0A
content_markdown: >
We talked before that we can use `macros` to simplify abstractions of our code.
Let us define a `macro` that has the functionality of a copy constructor
for a struct.
Notice that we group the macro's parameters using either `()` or `[]`.
The choice between using `()` and `[]` for `macro` invocations in Rust
often depends on the expected syntax and visual aesthetics. While `()` is more commonly associated with function calls and grouping expressions, `[]` is often associated with array indexing or indexing-like operations.
- title: Encapsulation With Methods
code: >-
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&code=struct%20SeaCreature%20%7B%0A%20%20%20%20noise%3A%20String%2C%0A%7D%0A%0Aimpl%20SeaCreature%20%7B%0A%20%20%20%20fn%20get_sound(%26self)%20-%3E%20%26str%20%7B%0A%20%20%20%20%20%20%20%20%26self.noise%0A%20%20%20%20%7D%0A%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20creature%20%3D%20SeaCreature%20%7B%0A%20%20%20%20%20%20%20%20noise%3A%20String%3A%3Afrom(%22blub%22)%2C%0A%20%20%20%20%7D%3B%0A%20%20%20%20println!(%22%7B%7D%22%2C%20creature.get_sound())%3B%0A%7D%0A
content_markdown: >
Rust supports the concept of an *object* that is a struct associated with
some functions (also known as *methods*).
The first parameter of any method must be a reference to the instance
associated with the method call (e.g. `instanceOfObj.foo()`). Rust uses:
* `&self` - Immutable reference to the instance.
* `&mut self` - Mutable reference to the instance.
Methods are defined within an implementation block with keyword `impl`:
```rust
impl MyStruct {
...
fn foo(&self) {
...
}
}
```
- title: Abstraction With Selective Exposure
code: >-
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&code=struct%20SeaCreature%20%7B%0A%20%20%20%20pub%20name%3A%20String%2C%0A%20%20%20%20noise%3A%20String%2C%0A%7D%0A%0Aimpl%20SeaCreature%20%7B%0A%20%20%20%20pub%20fn%20get_sound(%26self)%20-%3E%20%26str%20%7B%0A%20%20%20%20%20%20%20%20%26self.noise%0A%20%20%20%20%7D%0A%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20creature%20%3D%20SeaCreature%20%7B%0A%20%20%20%20%20%20%20%20name%3A%20String%3A%3Afrom(%22Ferris%22)%2C%0A%20%20%20%20%20%20%20%20noise%3A%20String%3A%3Afrom(%22blub%22)%2C%0A%20%20%20%20%7D%3B%0A%20%20%20%20println!(%22%7B%7D%22%2C%20creature.get_sound())%3B%0A%7D%0A
content_markdown: >
Rust can hide the inner workings of objects.
By default fields and methods are accessible only to the module they belong
to.
The `pub` keyword exposes struct fields and methods outside of the module.
- title: Polymorphism With Traits
code: >-
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&code=struct%20SeaCreature%20%7B%0A%20%20%20%20pub%20name%3A%20String%2C%0A%20%20%20%20noise%3A%20String%2C%0A%7D%0A%0Aimpl%20SeaCreature%20%7B%0A%20%20%20%20pub%20fn%20get_sound(%26self)%20-%3E%20%26str%20%7B%0A%20%20%20%20%20%20%20%20%26self.noise%0A%20%20%20%20%7D%0A%7D%0A%0Atrait%20NoiseMaker%20%7B%0A%20%20%20%20fn%20make_noise(%26self)%3B%0A%7D%0A%0Aimpl%20NoiseMaker%20for%20SeaCreature%20%7B%0A%20%20%20%20fn%20make_noise(%26self)%20%7B%0A%20%20%20%20%20%20%20%20println!(%22%7B%7D%22%2C%20%26self.get_sound())%3B%0A%20%20%20%20%7D%0A%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20creature%20%3D%20SeaCreature%20%7B%0A%20%20%20%20%20%20%20%20name%3A%20String%3A%3Afrom(%22Ferris%22)%2C%0A%20%20%20%20%20%20%20%20noise%3A%20String%3A%3Afrom(%22blub%22)%2C%0A%20%20%20%20%7D%3B%0A%20%20%20%20creature.make_noise()%3B%0A%7D%0A
content_markdown: >
Rust supports polymorphism with traits. Traits allow us to associate a set
of methods with a struct type.
We first define the signatures of methods of a trait within:
```
trait MyTrait {
fn foo(&self);
...
}
```
When a struct implements a trait, it establishes a contract that allows us
to indirectly interact with the struct
through the trait type (e.g. `&dyn MyTrait`) without having to know the real
type.
A struct's implemented traits methods are defined within an implementation
block:
```rust
impl MyTrait for MyStruct {
fn foo(&self) {
...
}
...
}
```
- title: Implemented Methods On Traits
code: >-
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&code=struct%20SeaCreature%20%7B%0A%20%20%20%20pub%20name%3A%20String%2C%0A%20%20%20%20noise%3A%20String%2C%0A%7D%0A%0Aimpl%20SeaCreature%20%7B%0A%20%20%20%20pub%20fn%20get_sound(%26self)%20-%3E%20%26str%20%7B%0A%20%20%20%20%20%20%20%20%26self.noise%0A%20%20%20%20%7D%0A%7D%0A%0Atrait%20NoiseMaker%20%7B%0A%20%20%20%20fn%20make_noise(%26self)%3B%0A%20%20%20%20%0A%20%20%20%20fn%20make_alot_of_noise(%26self)%7B%0A%20%20%20%20%20%20%20%20self.make_noise()%3B%0A%20%20%20%20%20%20%20%20self.make_noise()%3B%0A%20%20%20%20%20%20%20%20self.make_noise()%3B%0A%20%20%20%20%7D%0A%7D%0A%0Aimpl%20NoiseMaker%20for%20SeaCreature%20%7B%0A%20%20%20%20fn%20make_noise(%26self)%20%7B%0A%20%20%20%20%20%20%20%20println!(%22%7B%7D%22%2C%20%26self.get_sound())%3B%0A%20%20%20%20%7D%0A%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20creature%20%3D%20SeaCreature%20%7B%0A%20%20%20%20%20%20%20%20name%3A%20String%3A%3Afrom(%22Ferris%22)%2C%0A%20%20%20%20%20%20%20%20noise%3A%20String%3A%3Afrom(%22blub%22)%2C%0A%20%20%20%20%7D%3B%0A%20%20%20%20creature.make_alot_of_noise()%3B%0A%7D%0A
content_markdown: >
Traits can have implemented methods.
The functions have no direct access to the inner fields of a struct, but it
can
be useful for sharing behavior between many trait implementors.
- title: Trait Inheritance
code: >-
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&code=struct%20SeaCreature%20%7B%0A%20%20%20%20pub%20name%3A%20String%2C%0A%20%20%20%20noise%3A%20String%2C%0A%7D%0A%0Aimpl%20SeaCreature%20%7B%0A%20%20%20%20pub%20fn%20get_sound(%26self)%20-%3E%20%26str%20%7B%0A%20%20%20%20%20%20%20%20%26self.noise%0A%20%20%20%20%7D%0A%7D%0A%0Atrait%20NoiseMaker%20%7B%0A%20%20%20%20fn%20make_noise(%26self)%3B%0A%7D%0A%0Atrait%20LoudNoiseMaker%3A%20NoiseMaker%20%7B%0A%20%20%20%20fn%20make_alot_of_noise(%26self)%20%7B%0A%20%20%20%20%20%20%20%20self.make_noise()%3B%0A%20%20%20%20%20%20%20%20self.make_noise()%3B%0A%20%20%20%20%20%20%20%20self.make_noise()%3B%0A%20%20%20%20%7D%0A%7D%0A%0Aimpl%20NoiseMaker%20for%20SeaCreature%20%7B%0A%20%20%20%20fn%20make_noise(%26self)%20%7B%0A%20%20%20%20%20%20%20%20println!(%22%7B%7D%22%2C%20%26self.get_sound())%3B%0A%20%20%20%20%7D%0A%7D%0A%0Aimpl%20LoudNoiseMaker%20for%20SeaCreature%20%7B%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20creature%20%3D%20SeaCreature%20%7B%0A%20%20%20%20%20%20%20%20name%3A%20String%3A%3Afrom(%22Ferris%22)%2C%0A%20%20%20%20%20%20%20%20noise%3A%20String%3A%3Afrom(%22blub%22)%2C%0A%20%20%20%20%7D%3B%0A%20%20%20%20creature.make_alot_of_noise()%3B%0A%7D%0A
content_markdown: |
Traits can inherit methods from other traits.
- title: Dynamic vs Static Dispatch
code: >-
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&code=struct%20SeaCreature%20%7B%0A%20%20%20%20pub%20name%3A%20String%2C%0A%20%20%20%20noise%3A%20String%2C%0A%7D%0A%0Aimpl%20SeaCreature%20%7B%0A%20%20%20%20pub%20fn%20get_sound(%26self)%20-%3E%20%26str%20%7B%0A%20%20%20%20%20%20%20%20%26self.noise%0A%20%20%20%20%7D%0A%7D%0A%0Atrait%20NoiseMaker%20%7B%0A%20%20%20%20fn%20make_noise(%26self)%3B%0A%7D%0A%0Aimpl%20NoiseMaker%20for%20SeaCreature%20%7B%0A%20%20%20%20fn%20make_noise(%26self)%20%7B%0A%20%20%20%20%20%20%20%20println!(%22%7B%7D%22%2C%20%26self.get_sound())%3B%0A%20%20%20%20%7D%0A%7D%0A%0Afn%20static_make_noise(creature%3A%20%26SeaCreature)%20%7B%0A%20%20%20%20%2F%2F%20we%20know%20the%20real%20type%0A%20%20%20%20creature.make_noise()%3B%0A%7D%0A%0Afn%20dynamic_make_noise(noise_maker%3A%20%26dyn%20NoiseMaker)%20%7B%0A%20%20%20%20%2F%2F%20we%20don't%20know%20the%20real%20type%0A%20%20%20%20noise_maker.make_noise()%3B%0A%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20creature%20%3D%20SeaCreature%20%7B%0A%20%20%20%20%20%20%20%20name%3A%20String%3A%3Afrom(%22Ferris%22)%2C%0A%20%20%20%20%20%20%20%20noise%3A%20String%3A%3Afrom(%22blub%22)%2C%0A%20%20%20%20%7D%3B%0A%20%20%20%20static_make_noise(%26creature)%3B%0A%20%20%20%20dynamic_make_noise(%26creature)%3B%0A%7D%0A
content_markdown: >
Methods are executed in two ways:
* static dispatch - When the instance type is known, we have direct
knowledge of what function to call.
* dynamic dispatch - When an instance type is not known, we must find out
some way of calling the correct function.
Trait types `&dyn MyTrait` give us the ability to work with instances of
objects indirectly using dynamic dispatch.
When dynamic dispatch is used, Rust will encourage you to put `dyn` before
your trait type so people are aware.
Memory details:
* Dynamic dispatch is slightly slower because of the pointer chasing to find
the real function call.
- title: Trait Objects
content_markdown: >
When we pass an instance of an object to a parameter of type `&dyn MyTrait`
we pass what is called a *trait object*.
A trait object is what allows us to indirectly call the correct methods of
an instance. A trait object is a struct that holds the pointer of
our instance with a list of function pointers to our instance's methods.
Memory details:
* This list of functions is known in C++ as a *vtable*.
- title: Handling Unsized Data
content_markdown: >
Traits introduce an interesting challenge when we want to store them within
another struct. Traits obfuscate the original
struct thus it also obfuscates the original size. Unsized values being
stored in structs are handled in two ways in Rust:
* `generics` - Using parameterized types effectively create struct/functions
known types and thus known sizes.
* `indirection` - Putting instances on the heap gives us a level of
indirection that allow us to not have to worry about the size of the actual
type and just store a pointer to it. There are other ways as well!
- title: Generic Functions
code: >-
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&code=struct%20SeaCreature%20%7B%0A%20%20%20%20pub%20name%3A%20String%2C%0A%20%20%20%20noise%3A%20String%2C%0A%7D%0A%0Aimpl%20SeaCreature%20%7B%0A%20%20%20%20pub%20fn%20get_sound(%26self)%20-%3E%20%26str%20%7B%0A%20%20%20%20%20%20%20%20%26self.noise%0A%20%20%20%20%7D%0A%7D%0A%0Atrait%20NoiseMaker%20%7B%0A%20%20%20%20fn%20make_noise(%26self)%3B%0A%7D%0A%0Aimpl%20NoiseMaker%20for%20SeaCreature%20%7B%0A%20%20%20%20fn%20make_noise(%26self)%20%7B%0A%20%20%20%20%20%20%20%20println!(%22%7B%7D%22%2C%20%26self.get_sound())%3B%0A%20%20%20%20%7D%0A%7D%0A%0Afn%20generic_make_noise%3CT%3E(creature%3A%20%26T)%0Awhere%0A%20%20%20%20T%3A%20NoiseMaker%2C%0A%7B%0A%20%20%20%20%2F%2F%20we%20know%20the%20real%20type%20at%20compile-time%0A%20%20%20%20creature.make_noise()%3B%0A%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20creature%20%3D%20SeaCreature%20%7B%0A%20%20%20%20%20%20%20%20name%3A%20String%3A%3Afrom(%22Ferris%22)%2C%0A%20%20%20%20%20%20%20%20noise%3A%20String%3A%3Afrom(%22blub%22)%2C%0A%20%20%20%20%7D%3B%0A%20%20%20%20generic_make_noise(%26creature)%3B%0A%7D%0A
content_markdown: >
Generics in Rust work hand in hand with traits. When we describe a
parameterized type `T` we can constrain what types
can be used as an argument by listing what required traits the argument must
implement.
In this example type `T` must implement trait `Foo`:
```rust
fn my_function<T>(foo: T)
where
T:Foo
{
...
}
```
By using generics we create static typed functions at compile time that will
have known types and sizes, allowing us to
perform static dispatch and store as a sized value.
- title: Generic Function Shorthand
code: >-
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&code=struct%20SeaCreature%20%7B%0A%20%20%20%20pub%20name%3A%20String%2C%0A%20%20%20%20noise%3A%20String%2C%0A%7D%0A%0Aimpl%20SeaCreature%20%7B%0A%20%20%20%20pub%20fn%20get_sound(%26self)%20-%3E%20%26str%20%7B%0A%20%20%20%20%20%20%20%20%26self.noise%0A%20%20%20%20%7D%0A%7D%0A%0Atrait%20NoiseMaker%20%7B%0A%20%20%20%20fn%20make_noise(%26self)%3B%0A%7D%0A%0Aimpl%20NoiseMaker%20for%20SeaCreature%20%7B%0A%20%20%20%20fn%20make_noise(%26self)%20%7B%0A%20%20%20%20%20%20%20%20println!(%22%7B%7D%22%2C%20%26self.get_sound())%3B%0A%20%20%20%20%7D%0A%7D%0A%0Afn%20generic_make_noise(creature%3A%20%26impl%20NoiseMaker)%0A%7B%0A%20%20%20%20%2F%2F%20we%20know%20the%20real%20type%20at%20compile-time%0A%20%20%20%20creature.make_noise()%3B%0A%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20creature%20%3D%20SeaCreature%20%7B%0A%20%20%20%20%20%20%20%20name%3A%20String%3A%3Afrom(%22Ferris%22)%2C%0A%20%20%20%20%20%20%20%20noise%3A%20String%3A%3Afrom(%22blub%22)%2C%0A%20%20%20%20%7D%3B%0A%20%20%20%20generic_make_noise(%26creature)%3B%0A%7D%0A
content_markdown: |
Rust has a shorthand for expressing generics constrained by a trait:
```rust
fn my_function(foo: impl Foo) {
...
}
```
This is equivalent to writing:
```rust
fn my_function<T>(foo: T)
where
T:Foo
{
...
}
```
- title: Box
code: >-
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&code=struct%20SeaCreature%20%7B%0A%20%20%20%20pub%20name%3A%20String%2C%0A%20%20%20%20noise%3A%20String%2C%0A%7D%0A%0Aimpl%20SeaCreature%20%7B%0A%20%20%20%20pub%20fn%20get_sound(%26self)%20-%3E%20%26str%20%7B%0A%20%20%20%20%20%20%20%20%26self.noise%0A%20%20%20%20%7D%0A%7D%0A%0Atrait%20NoiseMaker%20%7B%0A%20%20%20%20fn%20make_noise(%26self)%3B%0A%7D%0A%0Aimpl%20NoiseMaker%20for%20SeaCreature%20%7B%0A%20%20%20%20fn%20make_noise(%26self)%20%7B%0A%20%20%20%20%20%20%20%20println!(%22%7B%7D%22%2C%20%26self.get_sound())%3B%0A%20%20%20%20%7D%0A%7D%0A%0Astruct%20Ocean%20%7B%0A%20%20%20%20animals%3A%20Vec%3CBox%3Cdyn%20NoiseMaker%3E%3E%2C%0A%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20ferris%20%3D%20SeaCreature%20%7B%0A%20%20%20%20%20%20%20%20name%3A%20String%3A%3Afrom(%22Ferris%22)%2C%0A%20%20%20%20%20%20%20%20noise%3A%20String%3A%3Afrom(%22blub%22)%2C%0A%20%20%20%20%7D%3B%0A%20%20%20%20let%20sarah%20%3D%20SeaCreature%20%7B%0A%20%20%20%20%20%20%20%20name%3A%20String%3A%3Afrom(%22Sarah%22)%2C%0A%20%20%20%20%20%20%20%20noise%3A%20String%3A%3Afrom(%22swish%22)%2C%0A%20%20%20%20%7D%3B%0A%20%20%20%20let%20ocean%20%3D%20Ocean%20%7B%0A%20%20%20%20%20%20%20%20animals%3A%20vec!%5BBox%3A%3Anew(ferris)%2C%20Box%3A%3Anew(sarah)%5D%2C%0A%20%20%20%20%7D%3B%0A%20%20%20%20for%20a%20in%20ocean.animals.iter()%20%7B%0A%20%20%20%20%20%20%20%20a.make_noise()%3B%0A%20%20%20%20%7D%0A%7D%0A
content_markdown: >
`Box` is a data structure that allows us to move our data from the stack to
the heap.
`Box` is a struct known as a *smart pointer* that holds the pointer to our
data on the heap.
Because `Box` is a struct with a known size (because it just holds a
pointer), it is
often used as a way to store a reference to something in a struct that must
know the size
of its fields.
`Box` is so common it can be used from anywhere:
```rust
Box::new(Foo { ... })
```
- title: Generic Structs Revisited
content_markdown: >
Generic structs can also have their parameterized types constrained by
traits.
```rust
struct MyStruct<T>
where
T: MyTrait
{
foo: T
...
}
```
Generic structs have their parameterized type in their implementation
blocks:
```rust
impl<T> MyStruct<T> {
...
}
```
- title: Chapter 7 - Conclusion
content_markdown: >
We now have more language features at hand to represent our ideas clearly!
Rust abstractions might be simple but they are powerful enough to make
working with code a joy. In this chapter, we caught a glimpse of smart
pointers
with `Box`. In the next chapter we'll learn about how smart pointers can
help us with other
specialized memory situations.
Resources:
* [Video - Object-oriented Programming in 7
minutes](https://www.youtube.com/watch?v=pTB0EiLXUC8)
* [Article - "The faster you unlearn OOP, the better for you and your
software"](https://dpc.pw/the-faster-you-unlearn-oop-the-better-for-you-and-your-software)