Skip to content

Commit 9e79bd0

Browse files
authored
Merge pull request #4060 from rust-lang/listing-for-final-chs
Use `<Listing>` for final chapters (after restructuring)
2 parents 68b4d35 + 7ce0849 commit 9e79bd0

14 files changed

+293
-307
lines changed

src/ch18-01-what-is-oo.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,30 +44,29 @@ on demand whenever anyone needs it. In other words, `AveragedCollection` will
4444
cache the calculated average for us. Listing 18-1 has the definition of the
4545
`AveragedCollection` struct:
4646

47-
<span class="filename">Filename: src/lib.rs</span>
47+
<Listing number="18-1" file-name="src/lib.rs" caption="Listing 18-1: An `AveragedCollection` struct that maintains a list of integers and the average of the items in the collection">
4848

4949
```rust,noplayground
5050
{{#rustdoc_include ../listings/ch18-oop/listing-18-01/src/lib.rs}}
5151
```
5252

53-
<span class="caption">Listing 18-1: An `AveragedCollection` struct that
54-
maintains a list of integers and the average of the items in the
55-
collection</span>
53+
</Listing>
5654

5755
The struct is marked `pub` so that other code can use it, but the fields within
5856
the struct remain private. This is important in this case because we want to
5957
ensure that whenever a value is added or removed from the list, the average is
6058
also updated. We do this by implementing `add`, `remove`, and `average` methods
6159
on the struct, as shown in Listing 18-2:
6260

61+
<Listing number="18-2" file-name="src/lib.rs" caption="Listing 18-2: Implementations of the public methods `add`, `remove`, and `average` on `AveragedCollection`">
62+
6363
<span class="filename">Filename: src/lib.rs</span>
6464

6565
```rust,noplayground
6666
{{#rustdoc_include ../listings/ch18-oop/listing-18-02/src/lib.rs:here}}
6767
```
6868

69-
<span class="caption">Listing 18-2: Implementations of the public methods
70-
`add`, `remove`, and `average` on `AveragedCollection`</span>
69+
</Listing>
7170

7271
The public methods `add`, `remove`, and `average` are the only ways to access
7372
or modify data in an instance of `AveragedCollection`. When an item is added

src/ch18-02-trait-objects.md

Lines changed: 16 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -66,41 +66,38 @@ behavior.
6666
Listing 18-3 shows how to define a trait named `Draw` with one method named
6767
`draw`:
6868

69-
<span class="filename">Filename: src/lib.rs</span>
69+
<Listing number="18-3" file-name="src/lib.rs" caption="Definition of the `Draw` trait">
7070

7171
```rust,noplayground
7272
{{#rustdoc_include ../listings/ch18-oop/listing-18-03/src/lib.rs}}
7373
```
7474

75-
<span class="caption">Listing 18-3: Definition of the `Draw` trait</span>
75+
</Listing>
7676

7777
This syntax should look familiar from our discussions on how to define traits
7878
in Chapter 10. Next comes some new syntax: Listing 18-4 defines a struct named
7979
`Screen` that holds a vector named `components`. This vector is of type
8080
`Box<dyn Draw>`, which is a trait object; it’s a stand-in for any type inside
8181
a `Box` that implements the `Draw` trait.
8282

83-
<span class="filename">Filename: src/lib.rs</span>
83+
<Listing number="18-4" file-name="src/lib.rs" caption="Definition of the `Screen` struct with a `components` field holding a vector of trait objects that implement the `Draw` trait">
8484

8585
```rust,noplayground
8686
{{#rustdoc_include ../listings/ch18-oop/listing-18-04/src/lib.rs:here}}
8787
```
8888

89-
<span class="caption">Listing 18-4: Definition of the `Screen` struct with a
90-
`components` field holding a vector of trait objects that implement the `Draw`
91-
trait</span>
89+
</Listing>
9290

9391
On the `Screen` struct, we’ll define a method named `run` that will call the
9492
`draw` method on each of its `components`, as shown in Listing 18-5:
9593

96-
<span class="filename">Filename: src/lib.rs</span>
94+
<Listing number="18-5" file-name="src/lib.rs" caption="A `run` method on `Screen` that calls the `draw` method on each component">
9795

9896
```rust,noplayground
9997
{{#rustdoc_include ../listings/ch18-oop/listing-18-05/src/lib.rs:here}}
10098
```
10199

102-
<span class="caption">Listing 18-5: A `run` method on `Screen` that calls the
103-
`draw` method on each component</span>
100+
</Listing>
104101

105102
This works differently from defining a struct that uses a generic type
106103
parameter with trait bounds. A generic type parameter can only be substituted
@@ -109,14 +106,13 @@ concrete types to fill in for the trait object at runtime. For example, we
109106
could have defined the `Screen` struct using a generic type and a trait bound
110107
as in Listing 18-6:
111108

112-
<span class="filename">Filename: src/lib.rs</span>
109+
<Listing number="18-6" file-name="src/lib.rs" caption="An alternate implementation of the `Screen` struct and its `run` method using generics and trait bounds">
113110

114111
```rust,noplayground
115112
{{#rustdoc_include ../listings/ch18-oop/listing-18-06/src/lib.rs:here}}
116113
```
117114

118-
<span class="caption">Listing 18-6: An alternate implementation of the `Screen`
119-
struct and its `run` method using generics and trait bounds</span>
115+
</Listing>
120116

121117
This restricts us to a `Screen` instance that has a list of components all of
122118
type `Button` or all of type `TextField`. If you’ll only ever have homogeneous
@@ -136,14 +132,13 @@ of this book, so the `draw` method won’t have any useful implementation in its
136132
body. To imagine what the implementation might look like, a `Button` struct
137133
might have fields for `width`, `height`, and `label`, as shown in Listing 18-7:
138134

139-
<span class="filename">Filename: src/lib.rs</span>
135+
<Listing number="18-7" file-name="src/lib.rs" caption="A `Button` struct that implements the `Draw` trait">
140136

141137
```rust,noplayground
142138
{{#rustdoc_include ../listings/ch18-oop/listing-18-07/src/lib.rs:here}}
143139
```
144140

145-
<span class="caption">Listing 18-7: A `Button` struct that implements the
146-
`Draw` trait</span>
141+
</Listing>
147142

148143
The `width`, `height`, and `label` fields on `Button` will differ from the
149144
fields on other components; for example, a `TextField` type might have those
@@ -159,29 +154,27 @@ If someone using our library decides to implement a `SelectBox` struct that has
159154
`width`, `height`, and `options` fields, they implement the `Draw` trait on the
160155
`SelectBox` type as well, as shown in Listing 18-8:
161156

162-
<span class="filename">Filename: src/main.rs</span>
157+
<Listing number="18-8" file-name="src/main.rs" caption="Another crate using `gui` and implementing the `Draw` trait on a `SelectBox` struct">
163158

164159
```rust,ignore
165160
{{#rustdoc_include ../listings/ch18-oop/listing-18-08/src/main.rs:here}}
166161
```
167162

168-
<span class="caption">Listing 18-8: Another crate using `gui` and implementing
169-
the `Draw` trait on a `SelectBox` struct</span>
163+
</Listing>
170164

171165
Our library’s user can now write their `main` function to create a `Screen`
172166
instance. To the `Screen` instance, they can add a `SelectBox` and a `Button`
173167
by putting each in a `Box<T>` to become a trait object. They can then call the
174168
`run` method on the `Screen` instance, which will call `draw` on each of the
175169
components. Listing 18-9 shows this implementation:
176170

177-
<span class="filename">Filename: src/main.rs</span>
171+
<Listing number="18-9" file-name="src/main.rs" caption="Using trait objects to store values of different types that implement the same trait">
178172

179173
```rust,ignore
180174
{{#rustdoc_include ../listings/ch18-oop/listing-18-09/src/main.rs:here}}
181175
```
182176

183-
<span class="caption">Listing 18-9: Using trait objects to store values of
184-
different types that implement the same trait</span>
177+
</Listing>
185178

186179
When we wrote the library, we didn’t know that someone might add the
187180
`SelectBox` type, but our `Screen` implementation was able to operate on the
@@ -208,14 +201,13 @@ our code if the values don’t implement the traits that the trait objects need.
208201
For example, Listing 18-10 shows what happens if we try to create a `Screen`
209202
with a `String` as a component:
210203

211-
<span class="filename">Filename: src/main.rs</span>
204+
<Listing number="18-10" file-name="src/main.rs" caption="Attempting to use a type that doesn’t implement the trait object’s trait">
212205

213206
```rust,ignore,does_not_compile
214207
{{#rustdoc_include ../listings/ch18-oop/listing-18-10/src/main.rs}}
215208
```
216209

217-
<span class="caption">Listing 18-10: Attempting to use a type that doesn’t
218-
implement the trait object’s trait</span>
210+
</Listing>
219211

220212
We’ll get this error because `String` doesn’t implement the `Draw` trait:
221213

src/ch18-03-oo-design-patterns.md

Lines changed: 25 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,13 @@ Listing 18-11 shows this workflow in code form: this is an example usage of the
4040
API we’ll implement in a library crate named `blog`. This won’t compile yet
4141
because we haven’t implemented the `blog` crate.
4242

43-
<span class="filename">Filename: src/main.rs</span>
43+
<Listing number="18-11" file-name="src/main.rs" caption="Code that demonstrates the desired behavior we want our `blog` crate to have">
4444

4545
```rust,ignore,does_not_compile
4646
{{#rustdoc_include ../listings/ch18-oop/listing-18-11/src/main.rs:all}}
4747
```
4848

49-
<span class="caption">Listing 18-11: Code that demonstrates the desired
50-
behavior we want our `blog` crate to have</span>
49+
</Listing>
5150

5251
We want to allow the user to create a new draft blog post with `Post::new`. We
5352
want to allow text to be added to the blog post. If we try to get the post’s
@@ -84,15 +83,13 @@ Then `Post` will hold a trait object of `Box<dyn State>` inside an `Option<T>`
8483
in a private field named `state` to hold the state object. You’ll see why the
8584
`Option<T>` is necessary in a bit.
8685

87-
<span class="filename">Filename: src/lib.rs</span>
86+
<Listing number="18-12" file-name="src/lib.rs" caption="Definition of a `Post` struct and a `new` function that creates a new `Post` instance, a `State` trait, and a `Draft` struct">
8887

8988
```rust,noplayground
9089
{{#rustdoc_include ../listings/ch18-oop/listing-18-12/src/lib.rs}}
9190
```
9291

93-
<span class="caption">Listing 18-12: Definition of a `Post` struct and a `new`
94-
function that creates a new `Post` instance, a `State` trait, and a `Draft`
95-
struct</span>
92+
</Listing>
9693

9794
The `State` trait defines the behavior shared by different post states. The
9895
state objects are `Draft`, `PendingReview`, and `Published`, and they will all
@@ -117,14 +114,13 @@ the `content` field’s data is read. The `add_text` method is pretty
117114
straightforward, so let’s add the implementation in Listing 18-13 to the `impl
118115
Post` block:
119116

120-
<span class="filename">Filename: src/lib.rs</span>
117+
<Listing number="18-13" fie-name="src/lib.rs" caption="Implementing the `add_text` method to add text to a post’s `content`">
121118

122119
```rust,noplayground
123120
{{#rustdoc_include ../listings/ch18-oop/listing-18-13/src/lib.rs:here}}
124121
```
125122

126-
<span class="caption">Listing 18-13: Implementing the `add_text` method to add
127-
text to a post’s `content`</span>
123+
</Listing>
128124

129125
The `add_text` method takes a mutable reference to `self`, because we’re
130126
changing the `Post` instance that we’re calling `add_text` on. We then call
@@ -145,14 +141,13 @@ once we implement the ability to change a post’s state so it can be published.
145141
So far, posts can only be in the draft state, so the post content should always
146142
be empty. Listing 18-14 shows this placeholder implementation:
147143

148-
<span class="filename">Filename: src/lib.rs</span>
144+
<Listing number="18-14" file-name="src/lib.rs" caption="Adding a placeholder implementation for the `content` method on `Post` that always returns an empty string slice">
149145

150146
```rust,noplayground
151147
{{#rustdoc_include ../listings/ch18-oop/listing-18-14/src/lib.rs:here}}
152148
```
153149

154-
<span class="caption">Listing 18-14: Adding a placeholder implementation for
155-
the `content` method on `Post` that always returns an empty string slice</span>
150+
</Listing>
156151

157152
With this added `content` method, everything in Listing 18-11 up to line 7
158153
works as intended.
@@ -162,14 +157,13 @@ works as intended.
162157
Next, we need to add functionality to request a review of a post, which should
163158
change its state from `Draft` to `PendingReview`. Listing 18-15 shows this code:
164159

165-
<span class="filename">Filename: src/lib.rs</span>
160+
<Listing number="18-15" file-name="src/lib.rs" caption="Implementing `request_review` methods on `Post` and the `State` trait">
166161

167162
```rust,noplayground
168163
{{#rustdoc_include ../listings/ch18-oop/listing-18-15/src/lib.rs:here}}
169164
```
170165

171-
<span class="caption">Listing 18-15: Implementing `request_review` methods on
172-
`Post` and the `State` trait</span>
166+
</Listing>
173167

174168
We give `Post` a public method named `request_review` that will take a mutable
175169
reference to `self`. Then we call an internal `request_review` method on the
@@ -222,14 +216,13 @@ The `approve` method will be similar to the `request_review` method: it will
222216
set `state` to the value that the current state says it should have when that
223217
state is approved, as shown in Listing 18-16:
224218

225-
<span class="filename">Filename: src/lib.rs</span>
219+
<Listing number="18-16" file-name="src/lib.rs" caption="Implementing the `approve` method on `Post` and the `State` trait">
226220

227221
```rust,noplayground
228222
{{#rustdoc_include ../listings/ch18-oop/listing-18-16/src/lib.rs:here}}
229223
```
230224

231-
<span class="caption">Listing 18-16: Implementing the `approve` method on
232-
`Post` and the `State` trait</span>
225+
</Listing>
233226

234227
We add the `approve` method to the `State` trait and add a new struct that
235228
implements `State`, the `Published` state.
@@ -247,14 +240,13 @@ returned from `content` to depend on the current state of the `Post`, so we’re
247240
going to have the `Post` delegate to a `content` method defined on its `state`,
248241
as shown in Listing 18-17:
249242

250-
<span class="filename">Filename: src/lib.rs</span>
243+
<Listing number="18-17" file-name="src/lib.rs" caption="Updating the `content` method on `Post` to delegate to a `content` method on `State`">
251244

252245
```rust,ignore,does_not_compile
253246
{{#rustdoc_include ../listings/ch18-oop/listing-18-17/src/lib.rs:here}}
254247
```
255248

256-
<span class="caption">Listing 18-17: Updating the `content` method on `Post` to
257-
delegate to a `content` method on `State`</span>
249+
</Listing>
258250

259251
Because the goal is to keep all these rules inside the structs that implement
260252
`State`, we call a `content` method on the value in `state` and pass the post
@@ -282,14 +274,13 @@ we need to add `content` to the `State` trait definition, and that is where
282274
we’ll put the logic for what content to return depending on which state we
283275
have, as shown in Listing 18-18:
284276

285-
<span class="filename">Filename: src/lib.rs</span>
277+
<Listing number="18-18" file-name="src/lib.rs" caption="Adding the `content` method to the `State` trait">
286278

287279
```rust,noplayground
288280
{{#rustdoc_include ../listings/ch18-oop/listing-18-18/src/lib.rs:here}}
289281
```
290282

291-
<span class="caption">Listing 18-18: Adding the `content` method to the `State`
292-
trait</span>
283+
</Listing>
293284

294285
We add a default implementation for the `content` method that returns an empty
295286
string slice. That means we don’t need to implement `content` on the `Draft`
@@ -383,12 +374,14 @@ draft posts where only published posts are allowed by issuing a compiler error.
383374

384375
Let’s consider the first part of `main` in Listing 18-11:
385376

386-
<span class="filename">Filename: src/main.rs</span>
377+
<Listing file-name="src/main.rs">
387378

388379
```rust,ignore
389380
{{#rustdoc_include ../listings/ch18-oop/listing-18-11/src/main.rs:here}}
390381
```
391382

383+
</Listing>
384+
392385
We still enable the creation of new posts in the draft state using `Post::new`
393386
and the ability to add text to the post’s content. But instead of having a
394387
`content` method on a draft post that returns an empty string, we’ll make it so
@@ -399,14 +392,13 @@ display draft post content in production, because that code won’t even compile
399392
Listing 18-19 shows the definition of a `Post` struct and a `DraftPost` struct,
400393
as well as methods on each:
401394

402-
<span class="filename">Filename: src/lib.rs</span>
395+
<Listing number="18-19" file-name="src/lib.rs" caption="A `Post` with a `content` method and `DraftPost` without a `content` method">
403396

404397
```rust,noplayground
405398
{{#rustdoc_include ../listings/ch18-oop/listing-18-19/src/lib.rs}}
406399
```
407400

408-
<span class="caption">Listing 18-19: A `Post` with a `content` method and a
409-
`DraftPost` without a `content` method</span>
401+
</Listing>
410402

411403
Both the `Post` and `DraftPost` structs have a private `content` field that
412404
stores the blog post text. The structs no longer have the `state` field because
@@ -435,15 +427,13 @@ these constraints by adding another struct, `PendingReviewPost`, defining the
435427
defining an `approve` method on `PendingReviewPost` to return a `Post`, as
436428
shown in Listing 18-20:
437429

438-
<span class="filename">Filename: src/lib.rs</span>
430+
<Listing number="18-20" file-name="src/lib.rs" caption="A `PendingReviewPost` that gets created by calling `request_review` on `DraftPost` and an `approve` method that turns a `PendingReviewPost` into a published `Post`">
439431

440432
```rust,noplayground
441433
{{#rustdoc_include ../listings/ch18-oop/listing-18-20/src/lib.rs:here}}
442434
```
443435

444-
<span class="caption">Listing 18-20: A `PendingReviewPost` that gets created by
445-
calling `request_review` on `DraftPost` and an `approve` method that turns a
446-
`PendingReviewPost` into a published `Post`</span>
436+
</Listing>
447437

448438
The `request_review` and `approve` methods take ownership of `self`, thus
449439
consuming the `DraftPost` and `PendingReviewPost` instances and transforming
@@ -465,14 +455,13 @@ pending review posts’ contents be empty strings, nor do we need them: we can
465455
compile code that tries to use the content of posts in those states any longer.
466456
The updated code in `main` is shown in Listing 18-21:
467457

468-
<span class="filename">Filename: src/main.rs</span>
458+
<Listing number="18-21" file-name="src/main.rs" caption="Modifications to `main` to use the new implementation of the blog post workflow">
469459

470460
```rust,ignore
471461
{{#rustdoc_include ../listings/ch18-oop/listing-18-21/src/main.rs}}
472462
```
473463

474-
<span class="caption">Listing 18-21: Modifications to `main` to use the new
475-
implementation of the blog post workflow</span>
464+
</Listing>
476465

477466
The changes we needed to make to `main` to reassign `post` mean that this
478467
implementation doesn’t quite follow the object-oriented state pattern anymore:

0 commit comments

Comments
 (0)