Skip to content

Commit 83eaade

Browse files
Merge pull request #2811 from rust-lang/ch5-edits
2 parents 91ecd33 + 794d33a commit 83eaade

File tree

15 files changed

+141
-56
lines changed

15 files changed

+141
-56
lines changed

listings/ch05-using-structs-to-structure-related-data/listing-05-01/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
// ANCHOR: here
22
struct User {
3+
active: bool,
34
username: String,
45
email: String,
56
sign_in_count: u64,
6-
active: bool,
77
}
88
// ANCHOR_END: here
99

listings/ch05-using-structs-to-structure-related-data/listing-05-02/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
struct User {
2+
active: bool,
23
username: String,
34
email: String,
45
sign_in_count: u64,
5-
active: bool,
66
}
77

88
fn main() {

listings/ch05-using-structs-to-structure-related-data/listing-05-03/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
struct User {
2+
active: bool,
23
username: String,
34
email: String,
45
sign_in_count: u64,
5-
active: bool,
66
}
77

88
fn main() {

listings/ch05-using-structs-to-structure-related-data/listing-05-04/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
struct User {
2+
active: bool,
23
username: String,
34
email: String,
45
sign_in_count: u64,
5-
active: bool,
66
}
77

88
// ANCHOR: here

listings/ch05-using-structs-to-structure-related-data/listing-05-05/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
struct User {
2+
active: bool,
23
username: String,
34
email: String,
45
sign_in_count: u64,
5-
active: bool,
66
}
77

88
// ANCHOR: here

listings/ch05-using-structs-to-structure-related-data/listing-05-06/src/main.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
struct User {
2+
active: bool,
23
username: String,
34
email: String,
45
sign_in_count: u64,
5-
active: bool,
66
}
77

88
fn main() {
@@ -15,9 +15,9 @@ fn main() {
1515

1616
// ANCHOR: here
1717
let user2 = User {
18-
email: String::from("[email protected]"),
19-
username: String::from("anotherusername567"),
2018
active: user1.active,
19+
username: user1.username,
20+
email: String::from("[email protected]"),
2121
sign_in_count: user1.sign_in_count,
2222
};
2323
// ANCHOR_END: here

listings/ch05-using-structs-to-structure-related-data/listing-05-07/src/main.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
struct User {
2+
active: bool,
23
username: String,
34
email: String,
45
sign_in_count: u64,
5-
active: bool,
66
}
77

88
fn main() {
@@ -16,7 +16,6 @@ fn main() {
1616
// ANCHOR: here
1717
let user2 = User {
1818
email: String::from("[email protected]"),
19-
username: String::from("anotherusername567"),
2019
..user1
2120
};
2221
// ANCHOR_END: here

listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
struct User {
2+
active: bool,
23
username: &str,
34
email: &str,
45
sign_in_count: u64,
5-
active: bool,
66
}
77

88
fn main() {

listings/ch05-using-structs-to-structure-related-data/no-listing-06-method-field-interaction/Cargo.lock

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[package]
2+
name = "rectangles"
3+
version = "0.1.0"
4+
edition = "2018"
5+
6+
[dependencies]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#[derive(Debug)]
2+
struct Rectangle {
3+
width: u32,
4+
height: u32,
5+
}
6+
7+
// ANCHOR: here
8+
impl Rectangle {
9+
fn width(&self) -> bool {
10+
self.width > 0
11+
}
12+
}
13+
14+
fn main() {
15+
let rect1 = Rectangle {
16+
width: 30,
17+
height: 50,
18+
};
19+
20+
if rect1.width() {
21+
println!("The rectangle has a nonzero width; it is {}", rect1.width);
22+
}
23+
}
24+
// ANCHOR_END: here

src/ch05-00-structs.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ A *struct*, or *structure*, is a custom data type that lets you name and
44
package together multiple related values that make up a meaningful group. If
55
you’re familiar with an object-oriented language, a *struct* is like an
66
object’s data attributes. In this chapter, we’ll compare and contrast tuples
7-
with structs, demonstrate how to use structs, and discuss how to define methods
8-
and associated functions to specify behavior associated with a struct’s data.
7+
with structs. We’ll demonstrate how to define and instantiate structs. We’ll
8+
discuss how to define associated functions, especially the kind of associated
9+
functions called *methods*, to specify behavior associated with a struct type.
910
Structs and enums (discussed in Chapter 6) are the building blocks for creating
1011
new types in your program’s domain to take full advantage of Rust’s compile
1112
time type checking.

src/ch05-01-defining-structs.md

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -94,17 +94,18 @@ than `email: email`.
9494
### Creating Instances From Other Instances With Struct Update Syntax
9595

9696
It’s often useful to create a new instance of a struct that uses most of an old
97-
instance’s values but changes some. You’ll do this using *struct update syntax*.
97+
instance’s values but changes some. You can do this using *struct update
98+
syntax*.
9899

99100
First, Listing 5-6 shows how we create a new `User` instance in `user2` without
100-
the update syntax. We set new values for `email` and `username` but otherwise
101-
use the same values from `user1` that we created in Listing 5-2.
101+
the update syntax. We set a new value for `email` but otherwise use the same
102+
values from `user1` that we created in Listing 5-2.
102103

103104
```rust
104105
{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-06/src/main.rs:here}}
105106
```
106107

107-
<span class="caption">Listing 5-6: Creating a new `User` instance using some of
108+
<span class="caption">Listing 5-6: Creating a new `User` instance using one of
108109
the values from `user1`</span>
109110

110111
Using struct update syntax, we can achieve the same effect with less code, as
@@ -115,13 +116,28 @@ explicitly set should have the same value as the fields in the given instance.
115116
{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-07/src/main.rs:here}}
116117
```
117118

118-
<span class="caption">Listing 5-7: Using struct update syntax to set new
119-
`email` and `username` values for a `User` instance but use the rest of the
120-
values from the fields of the instance in the `user1` variable</span>
119+
<span class="caption">Listing 5-7: Using struct update syntax to set a new
120+
`email` value for a `User` instance but use the rest of the values from
121+
`user1`</span>
121122

122123
The code in Listing 5-7 also creates an instance in `user2` that has a
123-
different value for `email` and `username` but has the same values for the
124-
`active` and `sign_in_count` fields from `user1`.
124+
different value for `email` but has the same values for the `username`,
125+
`active`, and `sign_in_count` fields from `user1`. The `..user1` must come last
126+
to specify that any remaining fields should get their values from the
127+
corresponding fields in `user1`, but we can choose to specify values for as
128+
many fields as we want in any order, regardless of the order of the fields in
129+
the struct’s definition.
130+
131+
Note that the struct update syntax is like assignment with `=` because it moves
132+
the data, just as we saw in the [“Ways Variables and Data Interact: Move”
133+
section][move]<!-- ignore -->. In this example, we can no longer use `user1`
134+
after creating `user2` because the `String` in the `username` field of `user1`
135+
was moved into `user2`. If we had given `user2` new `String` values for both
136+
`email` and `username`, and thus only used the `active` and `sign_in_count`
137+
values from `user1`, then `user1` would still be valid after creating `user2`.
138+
The types of `active` and `sign_in_count` are types that implement the `Copy`
139+
trait, so the behavior we discussed in the [“Stack-Only Data: Copy”
140+
section][copy]<!-- ignore --> would apply.
125141

126142
### Using Tuple Structs without Named Fields to Create Different Types
127143

@@ -258,3 +274,5 @@ paste above
258274
add `> ` before every line -->
259275
260276
[tuples]: ch03-02-data-types.html#the-tuple-type
277+
[move]: ch04-01-what-is-ownership.html#ways-variables-and-data-interact-move
278+
[copy]: ch04-01-what-is-ownership.html#stack-only-data-copy

src/ch05-02-example-structs.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -160,16 +160,16 @@ But again, the compiler gives us a helpful note:
160160

161161
Rust *does* include functionality to print out debugging information, but we
162162
have to explicitly opt in to make that functionality available for our struct.
163-
To do that, we add the annotation `#[derive(Debug)]` just before the struct
164-
definition, as shown in Listing 5-12.
163+
To do that, we add the outer attribute `#[derive(Debug)]` just before the
164+
struct definition, as shown in Listing 5-12.
165165

166166
<span class="filename">Filename: src/main.rs</span>
167167

168168
```rust
169169
{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-12/src/main.rs}}
170170
```
171171

172-
<span class="caption">Listing 5-12: Adding the annotation to derive the `Debug`
172+
<span class="caption">Listing 5-12: Adding the attribute to derive the `Debug`
173173
trait and printing the `Rectangle` instance using debug formatting</span>
174174

175175
Now when we run the program, we won’t get any errors, and we’ll see the
@@ -224,10 +224,12 @@ the `Rectangle` struct. This output uses the pretty `Debug` formatting of the
224224
figure out what your code is doing!
225225

226226
In addition to the `Debug` trait, Rust has provided a number of traits for us
227-
to use with the `derive` annotation that can add useful behavior to our custom
227+
to use with the `derive` attribute that can add useful behavior to our custom
228228
types. Those traits and their behaviors are listed in [Appendix C][app-c]<!--
229229
ignore -->. We’ll cover how to implement these traits with custom behavior as
230-
well as how to create your own traits in Chapter 10.
230+
well as how to create your own traits in Chapter 10. There are also many
231+
attributes other than `derive`; for more information, see [the “Attributes”
232+
section of the Rust Reference][attributes].
231233

232234
Our `area` function is very specific: it only computes the area of rectangles.
233235
It would be helpful to tie this behavior more closely to our `Rectangle`
@@ -240,3 +242,4 @@ continue to refactor this code by turning the `area` function into an `area`
240242
[println]: ../std/macro.println.html
241243
[dbg]: ../std/macro.dbg.html
242244
[err]: ch12-06-writing-to-stderr-instead-of-stdout.html
245+
[attributes]: ../reference/attributes.html

src/ch05-03-method-syntax.md

Lines changed: 58 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,24 @@ in Listing 5-13.
2424
`Rectangle` struct</span>
2525

2626
To define the function within the context of `Rectangle`, we start an `impl`
27-
(implementation) block. Then we move the `area` function within the `impl`
28-
curly brackets and change the first (and in this case, only) parameter to be
29-
`self` in the signature and everywhere within the body. In `main`, where we
30-
called the `area` function and passed `rect1` as an argument, we can instead
31-
use *method syntax* to call the `area` method on our `Rectangle` instance.
32-
The method syntax goes after an instance: we add a dot followed by the method
33-
name, parentheses, and any arguments.
34-
35-
In the signature for `area`, we use `&self` instead of `rectangle: &Rectangle`
36-
because Rust knows the type of `self` is `Rectangle` due to this method’s being
37-
inside the `impl Rectangle` context. Note that we still need to use the `&`
38-
before `self`, just as we did in `&Rectangle`. Methods can take ownership of
39-
`self`, borrow `self` immutably as we’ve done here, or borrow `self` mutably,
40-
just as they can any other parameter.
27+
(implementation) block for `Rectangle`. Everything within this `impl` block
28+
will be associated with the `Rectangle` type. Then we move the `area` function
29+
within the `impl` curly brackets and change the first (and in this case, only)
30+
parameter to be `self` in the signature and everywhere within the body. In
31+
`main`, where we called the `area` function and passed `rect1` as an argument,
32+
we can instead use *method syntax* to call the `area` method on our `Rectangle`
33+
instance. The method syntax goes after an instance: we add a dot followed by
34+
the method name, parentheses, and any arguments.
35+
36+
In the signature for `area`, we use `&self` instead of `rectangle: &Rectangle`.
37+
The `&self` is actually short for `self: &Self`. Within an `impl` block, the
38+
type `Self` is an alias for the type that the `impl` block is for. Methods must
39+
have a parameter named `self` of type `Self` for their first parameter, so Rust
40+
lets you abbreviate this with only the name `self` in the first parameter spot.
41+
Note that we still need to use the `&` in front of the `self` shorthand to
42+
indicate this method borrows the `Self` instance, just as we did in `rectangle:
43+
&Rectangle`. Methods can take ownership of `self`, borrow `self` immutably as
44+
we’ve done here, or borrow `self` mutably, just as they can any other parameter.
4145

4246
We’ve chosen `&self` here for the same reason we used `&Rectangle` in the
4347
function version: we don’t want to take ownership, and we just want to read the
@@ -55,6 +59,31 @@ instance of a type in one `impl` block rather than making future users of our
5559
code search for capabilities of `Rectangle` in various places in the library we
5660
provide.
5761

62+
Note that we can choose to give a method the same name as one of the struct’s
63+
fields. For example, we can define a method on `Rectangle` also named `width`:
64+
65+
<span class="filename">Filename: src/main.rs</span>
66+
67+
```rust
68+
{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/no-listing-06-method-field-interaction/src/main.rs:here}}
69+
```
70+
71+
Here, we’re choosing to make the behavior of the `width` method be that it
72+
returns `true` if the value in the instance’s `width` field is greater than 0,
73+
and `false` if the value is 0: we can use a field within a method of the same
74+
name for any purpose. In `main`, when we follow `rect1.width` with parentheses,
75+
Rust knows we mean the method `width`. When we don’t use parentheses, Rust
76+
knows we mean the field `width`.
77+
78+
Often, but not always, methods with the same name as a field will be defined to
79+
only return the value in the field and do nothing else. Methods like this are
80+
called *getters*, and Rust does not implement them automatically for struct
81+
fields as some other languages do. Getters are useful because you can make the
82+
field private but the method public and thus enable read-only access to that
83+
field as part of the type’s public API. We will be discussing what public and
84+
private are and how to designate a field or method as public or private in
85+
Chapter 7.
86+
5887
> ### Where’s the `->` Operator?
5988
>
6089
> In C and C++, two different operators are used for calling methods: you use
@@ -157,18 +186,18 @@ parameters in functions.
157186

158187
### Associated Functions
159188

160-
Another useful feature of `impl` blocks is that we’re allowed to define
161-
functions within `impl` blocks that *don’t* take `self` as a parameter. These
162-
are called *associated functions* because they’re associated with the struct.
163-
They’re still functions, not methods, because they don’t have an instance of
164-
the struct to work with. You’ve already used the `String::from` associated
165-
function.
189+
All functions defined within an `impl` block are called *associated functions*
190+
because they’re associated with the type named after the `impl`. We can define
191+
associated functions that don’t have `self` as their first parameter (and thus
192+
are not methods) because they don’t need an instance of the type to work with.
193+
We’ve already used one function like this, the `String::from` function, that’s
194+
defined on the `String` type.
166195

167-
Associated functions are often used for constructors that will return a new
168-
instance of the struct. For example, we could provide an associated function
169-
that would have one dimension parameter and use that as both width and height,
170-
thus making it easier to create a square `Rectangle` rather than having to
171-
specify the same value twice:
196+
Associated functions that aren’t methods are often used for constructors that
197+
will return a new instance of the struct. For example, we could provide an
198+
associated function that would have one dimension parameter and use that as
199+
both width and height, thus making it easier to create a square `Rectangle`
200+
rather than having to specify the same value twice:
172201

173202
<span class="filename">Filename: src/main.rs</span>
174203

@@ -202,10 +231,10 @@ useful in Chapter 10, where we discuss generic types and traits.
202231

203232
Structs let you create custom types that are meaningful for your domain. By
204233
using structs, you can keep associated pieces of data connected to each other
205-
and name each piece to make your code clear. Methods let you specify the
206-
behavior that instances of your structs have, and associated functions let you
207-
namespace functionality that is particular to your struct without having an
208-
instance available.
234+
and name each piece to make your code clear. In `impl` blocks, you can define
235+
functions that are associated with your type, and methods are a kind of
236+
associated function that let you specify the behavior that instances of your
237+
structs have.
209238

210239
But structs aren’t the only way you can create custom types: let’s turn to
211240
Rust’s enum feature to add another tool to your toolbox.

0 commit comments

Comments
 (0)