]> git.proxmox.com Git - rustc.git/blob - src/doc/book/nostarch/chapter05.md
New upstream version 1.63.0+dfsg1
[rustc.git] / src / doc / book / nostarch / chapter05.md
1 <!-- DO NOT EDIT THIS FILE.
2
3 This file is periodically generated from the content in the `/src/`
4 directory, so all fixes need to be made in `/src/`.
5 -->
6
7 [TOC]
8
9 # Using Structs to Structure Related Data
10
11 A *struct*, or *structure*, is a custom data type that lets you package
12 together and name multiple related values that make up a meaningful group. If
13 you’re familiar with an object-oriented language, a *struct* is like an
14 object’s data attributes. In this chapter, we’ll compare and contrast tuples
15 with structs to build on what you already know and demonstrate when structs are
16 a better way to group data.
17
18 We’ll demonstrate how to define and instantiate structs. We’ll discuss how to
19 define associated functions, especially the kind of associated functions called
20 *methods*, to specify behavior associated with a struct type. Structs and enums
21 (discussed in Chapter 6) are the building blocks for creating new types in your
22 program’s domain to take full advantage of Rust’s compile time type checking.
23
24 ## Defining and Instantiating Structs
25
26 Structs are similar to tuples, discussed in “The Tuple Type” section, in that
27 both hold multiple related values. Like tuples, the pieces of a struct can be
28 different types. Unlike with tuples, in a struct you’ll name each piece of data
29 so it’s clear what the values mean. Adding these names means that structs are
30 more flexible than tuples: you don’t have to rely on the order of the data to
31 specify or access the values of an instance.
32
33 To define a struct, we enter the keyword `struct` and name the entire struct. A
34 struct’s name should describe the significance of the pieces of data being
35 grouped together. Then, inside curly brackets, we define the names and types of
36 the pieces of data, which we call *fields*. For example, Listing 5-1 shows a
37 struct that stores information about a user account.
38
39 ```
40 struct User {
41 active: bool,
42 username: String,
43 email: String,
44 sign_in_count: u64,
45 }
46 ```
47
48 Listing 5-1: A `User` struct definition
49
50 To use a struct after we’ve defined it, we create an *instance* of that struct
51 by specifying concrete values for each of the fields. We create an instance by
52 stating the name of the struct and then add curly brackets containing `key:
53 value` pairs, where the keys are the names of the fields and the values are the
54 data we want to store in those fields. We don’t have to specify the fields in
55 the same order in which we declared them in the struct. In other words, the
56 struct definition is like a general template for the type, and instances fill
57 in that template with particular data to create values of the type. For
58 example, we can declare a particular user as shown in Listing 5-2.
59
60 ```
61 fn main() {
62 let user1 = User {
63 email: String::from("someone@example.com"),
64 username: String::from("someusername123"),
65 active: true,
66 sign_in_count: 1,
67 };
68 }
69 ```
70
71 Listing 5-2: Creating an instance of the `User` struct
72
73 To get a specific value from a struct, we use dot notation. For example, to
74 access this user’s email address, we use `user1.email`. If the instance is
75 mutable, we can change a value by using the dot notation and assigning into a
76 particular field. Listing 5-3 shows how to change the value in the `email`
77 field of a mutable `User` instance.
78
79 <!--- Do we want to mention that `user1.email` will move the field? We can't
80 just use `user1.email` multiple times re: "wherever we wanted
81 to use this value"
82 /JT --->
83 <!-- I don't really want to mention that, but I did reword to avoid the
84 implication that we can use the value wherever we wanted to. /Carol -->
85
86 ```
87 fn main() {
88 let mut user1 = User {
89 email: String::from("someone@example.com"),
90 username: String::from("someusername123"),
91 active: true,
92 sign_in_count: 1,
93 };
94
95 user1.email = String::from("anotheremail@example.com");
96 }
97 ```
98
99 Listing 5-3: Changing the value in the `email` field of a `User` instance
100
101 Note that the entire instance must be mutable; Rust doesn’t allow us to mark
102 only certain fields as mutable. As with any expression, we can construct a new
103 instance of the struct as the last expression in the function body to
104 implicitly return that new instance.
105
106 Listing 5-4 shows a `build_user` function that returns a `User` instance with
107 the given email and username. The `active` field gets the value of `true`, and
108 the `sign_in_count` gets a value of `1`.
109
110 ```
111 fn build_user(email: String, username: String) -> User {
112 User {
113 email: email,
114 username: username,
115 active: true,
116 sign_in_count: 1,
117 }
118 }
119 ```
120
121 Listing 5-4: A `build_user` function that takes an email and username and
122 returns a `User` instance
123
124 It makes sense to name the function parameters with the same name as the struct
125 fields, but having to repeat the `email` and `username` field names and
126 variables is a bit tedious. If the struct had more fields, repeating each name
127 would get even more annoying. Luckily, there’s a convenient shorthand!
128
129 ### Using the Field Init Shorthand
130
131 Because the parameter names and the struct field names are exactly the same in
132 Listing 5-4, we can use the *field init shorthand* syntax to rewrite
133 `build_user` so that it behaves exactly the same but doesn’t have the
134 repetition of `email` and `username`, as shown in Listing 5-5.
135
136 ```
137 fn build_user(email: String, username: String) -> User {
138 User {
139 email,
140 username,
141 active: true,
142 sign_in_count: 1,
143 }
144 }
145 ```
146
147 Listing 5-5: A `build_user` function that uses field init shorthand because the
148 `email` and `username` parameters have the same name as struct fields
149
150 Here, we’re creating a new instance of the `User` struct, which has a field
151 named `email`. We want to set the `email` field’s value to the value in the
152 `email` parameter of the `build_user` function. Because the `email` field and
153 the `email` parameter have the same name, we only need to write `email` rather
154 than `email: email`.
155
156 ### Creating Instances From Other Instances With Struct Update Syntax
157
158 It’s often useful to create a new instance of a struct that includes most of
159 the values from another instance, but changes some. You can do this using
160 *struct update syntax*.
161
162 First, in Listing 5-6 we show how to create a new `User` instance in `user2`
163 regularly, without the update syntax. We set a new value for `email` but
164 otherwise use the same values from `user1` that we created in Listing 5-2.
165
166 ```
167 fn main() {
168 // --snip--
169
170 let user2 = User {
171 active: user1.active,
172 username: user1.username,
173 email: String::from("another@example.com"),
174 sign_in_count: user1.sign_in_count,
175 };
176 }
177 ```
178
179 Listing 5-6: Creating a new `User` instance using one of the values from `user1`
180
181 Using struct update syntax, we can achieve the same effect with less code, as
182 shown in Listing 5-7. The syntax `..` specifies that the remaining fields not
183 explicitly set should have the same value as the fields in the given instance.
184
185 ```
186 fn main() {
187 // --snip--
188
189 let user2 = User {
190 email: String::from("another@example.com"),
191 ..user1
192 };
193 }
194 ```
195
196 Listing 5-7: Using struct update syntax to set a new `email` value for a `User`
197 instance but use the rest of the values from `user1`
198
199 The code in Listing 5-7 also creates an instance in `user2` that has a
200 different value for `email` but has the same values for the `username`,
201 `active`, and `sign_in_count` fields from `user1`. The `..user1` must come last
202 to specify that any remaining fields should get their values from the
203 corresponding fields in `user1`, but we can choose to specify values for as
204 many fields as we want in any order, regardless of the order of the fields in
205 the struct’s definition.
206
207 Note that the struct update syntax uses `=` like an assignment; this is
208 because it moves the data, just as we saw in the “Ways Variables and Data
209 Interact: Move” section. In this example, we can no longer use `user1` after
210 creating `user2` because the `String` in the `username` field of `user1` was
211 moved into `user2`. If we had given `user2` new `String` values for both
212 `email` and `username`, and thus only used the `active` and `sign_in_count`
213 values from `user1`, then `user1` would still be valid after creating `user2`.
214 The types of `active` and `sign_in_count` are types that implement the `Copy`
215 trait, so the behavior we discussed in the “Stack-Only Data: Copy” section
216 would apply.
217
218 <!--- Misspelled "assignment" above.
219 /JT --->
220 <!-- Fixed! /Carol -->
221
222 ### Using Tuple Structs without Named Fields to Create Different Types
223
224 Rust also supports structs that look similar to tuples, called *tuple
225 structs*. Tuple structs have the added meaning the struct name provides but
226 don’t have names associated with their fields; rather, they just have the types
227 of the fields. Tuple structs are useful when you want to give the whole tuple a
228 name and make the tuple a different type from other tuples, and when naming each
229 field as in a regular struct would be verbose or redundant.
230
231 To define a tuple struct, start with the `struct` keyword and the struct name
232 followed by the types in the tuple. For example, here we define and use
233 two tuple structs named `Color` and `Point`:
234
235 ```
236 struct Color(i32, i32, i32);
237 struct Point(i32, i32, i32);
238
239 fn main() {
240 let black = Color(0, 0, 0);
241 let origin = Point(0, 0, 0);
242 }
243 ```
244
245 Note that the `black` and `origin` values are different types, because they’re
246 instances of different tuple structs. Each struct you define is its own type,
247 even though the fields within the struct might have the same types. For
248 example, a function that takes a parameter of type `Color` cannot take a
249 `Point` as an argument, even though both types are made up of three `i32`
250 values. Otherwise, tuple struct instances are similar to tuples in that you can
251 destructure them into their individual pieces, and you can use a `.` followed
252 by the index to access an individual value.
253
254 <!--- The last line above feels a bit misleading. There are related
255 restrictions on tuple structs that don't apply to tuples.
256
257 One example is you can't create a tuple struct with a tuple.
258 ```
259 struct Color(i32, i32, i32);
260
261 fn main() {
262 let x: Color = (1, 2, 3);
263 }
264 ```
265
266 You can't pass a tuple struct to something that expects a tuple, either.
267 /JT --->
268 <!-- I've reworded to avoid that implication /Carol -->
269
270 ### Unit-Like Structs Without Any Fields
271
272 You can also define structs that don’t have any fields! These are called
273 *unit-like structs* because they behave similarly to `()`, the unit type that
274 we mentioned in “The Tuple Type” section. Unit-like structs can be useful when
275 you need to implement a trait on some type but don’t have any data that you
276 want to store in the type itself. We’ll discuss traits in Chapter 10. Here’s an
277 example of declaring and instantiating a unit struct named `AlwaysEqual`:
278
279 ```
280 struct AlwaysEqual;
281
282 fn main() {
283 let subject = AlwaysEqual;
284 }
285 ```
286
287 To define `AlwaysEqual`, we use the `struct` keyword, the name we want, then a
288 semicolon. No need for curly brackets or parentheses! Then we can get an
289 instance of `AlwaysEqual` in the `subject` variable in a similar way: using the
290 name we defined, without any curly brackets or parentheses. Imagine that later
291 we’ll implement behavior for this type such that every instance of
292 `AlwaysEqual` is always equal to every instance of any other type, perhaps to
293 have a known result for testing purposes. We wouldn’t need any data to
294 implement that behavior! You’ll see in Chapter 10 how to define traits and
295 implement them on any type, including unit-like structs.
296
297 > ### Ownership of Struct Data
298 >
299 > In the `User` struct definition in Listing 5-1, we used the owned `String`
300 > type rather than the `&str` string slice type. This is a deliberate choice
301 > because we want each instance of this struct to own all of its data and for
302 > that data to be valid for as long as the entire struct is valid.
303 >
304 > It’s also possible for structs to store references to data owned by something
305 > else, but to do so requires the use of *lifetimes*, a Rust feature that we’ll
306 > discuss in Chapter 10. Lifetimes ensure that the data referenced by a struct
307 > is valid for as long as the struct is. Let’s say you try to store a reference
308 > in a struct without specifying lifetimes, like the following; this won’t work:
309 >
310 > Filename: src/main.rs
311 >
312 > ```
313 > struct User {
314 > username: &str,
315 > email: &str,
316 > sign_in_count: u64,
317 > active: bool,
318 > }
319 >
320 > fn main() {
321 > let user1 = User {
322 > email: "someone@example.com",
323 > username: "someusername123",
324 > active: true,
325 > sign_in_count: 1,
326 > };
327 > }
328 > ```
329 >
330 > The compiler will complain that it needs lifetime specifiers:
331 >
332 > ```
333 > $ cargo run
334 > Compiling structs v0.1.0 (file:///projects/structs)
335 > error[E0106]: missing lifetime specifier
336 > --> src/main.rs:3:15
337 > |
338 > 3 | username: &str,
339 > | ^ expected named lifetime parameter
340 > |
341 > help: consider introducing a named lifetime parameter
342 > |
343 > 1 ~ struct User<'a> {
344 > 2 | active: bool,
345 > 3 ~ username: &'a str,
346 > |
347 >
348 > error[E0106]: missing lifetime specifier
349 > --> src/main.rs:4:12
350 > |
351 > 4 | email: &str,
352 > | ^ expected named lifetime parameter
353 > |
354 > help: consider introducing a named lifetime parameter
355 > |
356 > 1 ~ struct User<'a> {
357 > 2 | active: bool,
358 > 3 | username: &str,
359 > 4 ~ email: &'a str,
360 > |
361 > ```
362 >
363 > In Chapter 10, we’ll discuss how to fix these errors so you can store
364 > references in structs, but for now, we’ll fix errors like these using owned
365 > types like `String` instead of references like `&str`.
366
367 ## An Example Program Using Structs
368
369 To understand when we might want to use structs, let’s write a program that
370 calculates the area of a rectangle. We’ll start by using single variables, and
371 then refactor the program until we’re using structs instead.
372
373 Let’s make a new binary project with Cargo called *rectangles* that will take
374 the width and height of a rectangle specified in pixels and calculate the area
375 of the rectangle. Listing 5-8 shows a short program with one way of doing
376 exactly that in our project’s *src/main.rs*.
377
378 Filename: src/main.rs
379
380 ```
381 fn main() {
382 let width1 = 30;
383 let height1 = 50;
384
385 println!(
386 "The area of the rectangle is {} square pixels.",
387 area(width1, height1)
388 );
389 }
390
391 fn area(width: u32, height: u32) -> u32 {
392 width * height
393 }
394 ```
395
396 Listing 5-8: Calculating the area of a rectangle specified by separate width
397 and height variables
398
399 Now, run this program using `cargo run`:
400
401 ```
402 $ cargo run
403 Compiling rectangles v0.1.0 (file:///projects/rectangles)
404 Finished dev [unoptimized + debuginfo] target(s) in 0.42s
405 Running `target/debug/rectangles`
406 The area of the rectangle is 1500 square pixels.
407 ```
408
409 This code succeeds in figuring out the area of the rectangle by calling the
410 `area` function with each dimension, but we can do more to make this code clear
411 and readable.
412
413 The issue with this code is evident in the signature of `area`:
414
415 ```
416 fn area(width: u32, height: u32) -> u32 {
417 ```
418
419 The `area` function is supposed to calculate the area of one rectangle, but the
420 function we wrote has two parameters, and it's not clear anywhere in our
421 program that the parameters are related. It would be more readable and more
422 manageable to group width and height together. We’ve already discussed one way
423 we might do that in “The Tuple Type” section of Chapter 3: by using tuples.
424
425 ### Refactoring with Tuples
426
427 Listing 5-9 shows another version of our program that uses tuples.
428
429 Filename: src/main.rs
430
431 ```
432 fn main() {
433 let rect1 = (30, 50);
434
435 println!(
436 "The area of the rectangle is {} square pixels.",
437 area(rect1)
438 );
439 }
440
441 fn area(dimensions: (u32, u32)) -> u32 {
442 dimensions.0 * dimensions.1
443 }
444 ```
445
446 Listing 5-9: Specifying the width and height of the rectangle with a tuple
447
448 In one way, this program is better. Tuples let us add a bit of structure, and
449 we’re now passing just one argument. But in another way, this version is less
450 clear: tuples don’t name their elements, so we have to index into the parts of
451 the tuple, making our calculation less obvious.
452
453 Mixing up the width and height wouldn’t matter for the area calculation, but if
454 we want to draw the rectangle on the screen, it would matter! We would have to
455 keep in mind that `width` is the tuple index `0` and `height` is the tuple
456 index `1`. This would be even harder for someone else to figure out and keep in
457 mind if they were to use our code. Because we haven’t conveyed the meaning of
458 our data in our code, it’s now easier to introduce errors.
459
460 ### Refactoring with Structs: Adding More Meaning
461
462 We use structs to add meaning by labeling the data. We can transform the tuple
463 we’re using into a struct with a name for the whole as well as names for the
464 parts, as shown in Listing 5-10.
465
466 Filename: src/main.rs
467
468 ```
469 struct Rectangle {
470 width: u32,
471 height: u32,
472 }
473
474 fn main() {
475 let rect1 = Rectangle {
476 width: 30,
477 height: 50,
478 };
479
480 println!(
481 "The area of the rectangle is {} square pixels.",
482 area(&rect1)
483 );
484 }
485
486 fn area(rectangle: &Rectangle) -> u32 {
487 rectangle.width * rectangle.height
488 }
489 ```
490
491 Listing 5-10: Defining a `Rectangle` struct
492
493 Here we’ve defined a struct and named it `Rectangle`. Inside the curly
494 brackets, we defined the fields as `width` and `height`, both of which have
495 type `u32`. Then in `main`, we created a particular instance of `Rectangle`
496 that has a width of 30 and a height of 50.
497
498 Our `area` function is now defined with one parameter, which we’ve named
499 `rectangle`, whose type is an immutable borrow of a struct `Rectangle`
500 instance. As mentioned in Chapter 4, we want to borrow the struct rather than
501 take ownership of it. This way, `main` retains its ownership and can continue
502 using `rect1`, which is the reason we use the `&` in the function signature and
503 where we call the function.
504
505 The `area` function accesses the `width` and `height` fields of the `Rectangle`
506 instance (note that accessing fields of a borrowed struct instance does not
507 move the field values, which is why you often see borrows of structs). Our
508 function signature for `area` now says exactly what we mean: calculate the area
509 of `Rectangle`, using its `width` and `height` fields. This conveys that the
510 width and height are related to each other, and it gives descriptive names to
511 the values rather than using the tuple index values of `0` and `1`. This is a
512 win for clarity.
513
514 <!--- Tying to my comment above about `user1.email` moving that field: we should
515 take a minute here and explain that accessing fields on a borrowed struct does
516 not move them, and why you often see borrows of structs.
517 /JT --->
518 <!-- I've added a note in the paragraph above; I haven't really seen people
519 struggle with that concept though so I don't want to spend too much time on it
520 /Carol -->
521
522 ### Adding Useful Functionality with Derived Traits
523
524 It’d be useful to be able to print an instance of `Rectangle` while we’re
525 debugging our program and see the values for all its fields. Listing 5-11 tries
526 using the `println!` macro as we have used in previous chapters. This won’t
527 work, however.
528
529 Filename: src/main.rs
530
531 ```
532 struct Rectangle {
533 width: u32,
534 height: u32,
535 }
536
537 fn main() {
538 let rect1 = Rectangle {
539 width: 30,
540 height: 50,
541 };
542
543 println!("rect1 is {}", rect1);
544 }
545 ```
546
547 Listing 5-11: Attempting to print a `Rectangle` instance
548
549 When we compile this code, we get an error with this core message:
550
551 ```
552 error[E0277]: `Rectangle` doesn't implement `std::fmt::Display`
553 ```
554
555 The `println!` macro can do many kinds of formatting, and by default, the curly
556 brackets tell `println!` to use formatting known as `Display`: output intended
557 for direct end user consumption. The primitive types we’ve seen so far
558 implement `Display` by default, because there’s only one way you’d want to show
559 a `1` or any other primitive type to a user. But with structs, the way
560 `println!` should format the output is less clear because there are more
561 display possibilities: Do you want commas or not? Do you want to print the
562 curly brackets? Should all the fields be shown? Due to this ambiguity, Rust
563 doesn’t try to guess what we want, and structs don’t have a provided
564 implementation of `Display` to use with `println!` and the `{}` placeholder.
565
566 If we continue reading the errors, we’ll find this helpful note:
567
568 ```
569 = help: the trait `std::fmt::Display` is not implemented for `Rectangle`
570 = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
571 ```
572
573 Let’s try it! The `println!` macro call will now look like `println!("rect1 is
574 {:?}", rect1);`. Putting the specifier `:?` inside the curly brackets tells
575 `println!` we want to use an output format called `Debug`. The `Debug` trait
576 enables us to print our struct in a way that is useful for developers so we can
577 see its value while we’re debugging our code.
578
579 Compile the code with this change. Drat! We still get an error:
580
581 ```
582 error[E0277]: `Rectangle` doesn't implement `Debug`
583 ```
584
585 But again, the compiler gives us a helpful note:
586
587 ```
588 = help: the trait `Debug` is not implemented for `Rectangle`
589 = note: add `#[derive(Debug)]` or manually implement `Debug`
590 ```
591
592 Rust *does* include functionality to print out debugging information, but we
593 have to explicitly opt in to make that functionality available for our struct.
594 To do that, we add the outer attribute `#[derive(Debug)]` just before the
595 struct definition, as shown in Listing 5-12.
596
597 Filename: src/main.rs
598
599 ```
600 #[derive(Debug)]
601 struct Rectangle {
602 width: u32,
603 height: u32,
604 }
605
606 fn main() {
607 let rect1 = Rectangle {
608 width: 30,
609 height: 50,
610 };
611
612 println!("rect1 is {:?}", rect1);
613 }
614 ```
615
616 Listing 5-12: Adding the attribute to derive the `Debug` trait and printing the
617 `Rectangle` instance using debug formatting
618
619 Now when we run the program, we won’t get any errors, and we’ll see the
620 following output:
621
622 ```
623 $ cargo run
624 Compiling rectangles v0.1.0 (file:///projects/rectangles)
625 Finished dev [unoptimized + debuginfo] target(s) in 0.48s
626 Running `target/debug/rectangles`
627 rect1 is Rectangle { width: 30, height: 50 }
628 ```
629
630 Nice! It’s not the prettiest output, but it shows the values of all the fields
631 for this instance, which would definitely help during debugging. When we have
632 larger structs, it’s useful to have output that’s a bit easier to read; in
633 those cases, we can use `{:#?}` instead of `{:?}` in the `println!` string.
634 In this example, using the `{:#?}` style will output:
635
636 ```
637 $ cargo run
638 Compiling rectangles v0.1.0 (file:///projects/rectangles)
639 Finished dev [unoptimized + debuginfo] target(s) in 0.48s
640 Running `target/debug/rectangles`
641 rect1 is Rectangle {
642 width: 30,
643 height: 50,
644 }
645 ```
646
647 Another way to print out a value using the `Debug` format is to use the `dbg!`
648 macro, which takes ownership of an expression (as opposed to `println!` that
649 takes a reference), prints the file and line number of where that `dbg!` macro
650 call occurs in your code along with the resulting value of that expression, and
651 returns ownership of the value.
652
653 > Note: Calling the `dbg!` macro prints to the standard error console stream
654 > (`stderr`), as opposed to `println!` which prints to the standard output
655 > console stream (`stdout`). We’ll talk more about `stderr` and `stdout` in the
656 > “Writing Error Messages to Standard Error Instead of Standard Output” section
657 > in Chapter 12.
658
659 Here’s an example where we’re interested in the value that gets assigned to the
660 `width` field, as well as the value of the whole struct in `rect1`:
661
662 ```
663 #[derive(Debug)]
664 struct Rectangle {
665 width: u32,
666 height: u32,
667 }
668
669 fn main() {
670 let scale = 2;
671 let rect1 = Rectangle {
672 width: dbg!(30 * scale),
673 height: 50,
674 };
675
676 dbg!(&rect1);
677 }
678 ```
679
680 We can put `dbg!` around the expression `30 * scale` and, because `dbg!`
681 returns ownership of the expression’s value, the `width` field will get the
682 same value as if we didn’t have the `dbg!` call there. We don’t want `dbg!` to
683 take ownership of `rect1`, so we use a reference to `rect1` in the next call.
684 Here’s what the output of this example looks like:
685
686 <!--- is it worth calling out that println! doesn't have the dbg! shortcoming
687 of taking ownership?
688 /JT --->
689 <!-- I added a note in the paragraph above that starts with "Another way to
690 print out a value" /Carol -->
691
692 ```
693 $ cargo run
694 Compiling rectangles v0.1.0 (file:///projects/rectangles)
695 Finished dev [unoptimized + debuginfo] target(s) in 0.61s
696 Running `target/debug/rectangles`
697 [src/main.rs:10] 30 * scale = 60
698 [src/main.rs:14] &rect1 = Rectangle {
699 width: 60,
700 height: 50,
701 }
702 ```
703
704 We can see the first bit of output came from *src/main.rs* line 10, where we’re
705 debugging the expression `30 * scale`, and its resulting value is 60 (the
706 `Debug` formatting implemented for integers is to print only their value). The
707 `dbg!` call on line 14 of *src/main.rs* outputs the value of `&rect1`, which is
708 the `Rectangle` struct. This output uses the pretty `Debug` formatting of the
709 `Rectangle` type. The `dbg!` macro can be really helpful when you’re trying to
710 figure out what your code is doing!
711
712 In addition to the `Debug` trait, Rust has provided a number of traits for us
713 to use with the `derive` attribute that can add useful behavior to our custom
714 types. Those traits and their behaviors are listed in Appendix C. We’ll cover
715 how to implement these traits with custom behavior as well as how to create
716 your own traits in Chapter 10. There are also many attributes other than
717 `derive`; for more information, see the “Attributes” section of the Rust
718 Reference at *https://doc.rust-lang.org/reference/attributes.html*.
719
720 Our `area` function is very specific: it only computes the area of rectangles.
721 It would be helpful to tie this behavior more closely to our `Rectangle`
722 struct, because it won’t work with any other type. Let’s look at how we can
723 continue to refactor this code by turning the `area` function into an `area`
724 *method* defined on our `Rectangle` type.
725
726 ## Method Syntax
727
728 *Methods* are similar to functions: we declare them with the `fn` keyword and a
729 name, they can have parameters and a return value, and they contain some code
730 that’s run when the method is called from somewhere else. Unlike functions,
731 methods are defined within the context of a struct (or an enum or a trait
732 object, which we cover in Chapters 6 and 17, respectively), and their first
733 parameter is always `self`, which represents the instance of the struct the
734 method is being called on.
735
736 <!--- minor nit: some folks call the non-self functions in an `impl`
737 "static methods" as a nod to OO languages that do the same. For folks
738 from that background, we may want to call out that instance methods always
739 have `self` and methods on the type do not.
740 /JT --->
741 <!-- This paragraph already says "their first parameter is always `self`", and
742 we get into associated functions in just a bit. I don't want to distract with
743 that info here; not changing anything at this spot. /Carol -->
744
745 ### Defining Methods
746
747 Let’s change the `area` function that has a `Rectangle` instance as a parameter
748 and instead make an `area` method defined on the `Rectangle` struct, as shown
749 in Listing 5-13.
750
751 Filename: src/main.rs
752
753 ```
754 #[derive(Debug)]
755 struct Rectangle {
756 width: u32,
757 height: u32,
758 }
759
760 impl Rectangle {
761 fn area(&self) -> u32 {
762 self.width * self.height
763 }
764 }
765
766 fn main() {
767 let rect1 = Rectangle {
768 width: 30,
769 height: 50,
770 };
771
772 println!(
773 "The area of the rectangle is {} square pixels.",
774 rect1.area()
775 );
776 }
777 ```
778
779 Listing 5-13: Defining an `area` method on the `Rectangle` struct
780
781 To define the function within the context of `Rectangle`, we start an `impl`
782 (implementation) block for `Rectangle`. Everything within this `impl` block
783 will be associated with the `Rectangle` type. Then we move the `area` function
784 within the `impl` curly brackets and change the first (and in this case, only)
785 parameter to be `self` in the signature and everywhere within the body. In
786 `main`, where we called the `area` function and passed `rect1` as an argument,
787 we can instead use *method syntax* to call the `area` method on our `Rectangle`
788 instance. The method syntax goes after an instance: we add a dot followed by
789 the method name, parentheses, and any arguments.
790
791 In the signature for `area`, we use `&self` instead of `rectangle: &Rectangle`.
792 The `&self` is actually short for `self: &Self`. Within an `impl` block, the
793 type `Self` is an alias for the type that the `impl` block is for. Methods must
794 have a parameter named `self` of type `Self` for their first parameter, so Rust
795 lets you abbreviate this with only the name `self` in the first parameter spot.
796 Note that we still need to use the `&` in front of the `self` shorthand to
797 indicate this method borrows the `Self` instance, just as we did in `rectangle:
798 &Rectangle`. Methods can take ownership of `self`, borrow `self` immutably as
799 we’ve done here, or borrow `self` mutably, just as they can any other parameter.
800
801 We’ve chosen `&self` here for the same reason we used `&Rectangle` in the
802 function version: we don’t want to take ownership, and we just want to read the
803 data in the struct, not write to it. If we wanted to change the instance that
804 we’ve called the method on as part of what the method does, we’d use `&mut
805 self` as the first parameter. Having a method that takes ownership of the
806 instance by using just `self` as the first parameter is rare; this technique is
807 usually used when the method transforms `self` into something else and you want
808 to prevent the caller from using the original instance after the transformation.
809
810 The main reason for using methods instead of functions, in addition to providing
811 method syntax and not having to repeat the type of `self` in every method’s
812 signature, is for organization. We’ve put all the things we can do with an
813 instance of a type in one `impl` block rather than making future users of our
814 code search for capabilities of `Rectangle` in various places in the library we
815 provide.
816
817 Note that we can choose to give a method the same name as one of the struct’s
818 fields. For example, we can define a method on `Rectangle` also named `width`:
819
820 Filename: src/main.rs
821
822 ```
823 impl Rectangle {
824 fn width(&self) -> bool {
825 self.width > 0
826 }
827 }
828
829 fn main() {
830 let rect1 = Rectangle {
831 width: 30,
832 height: 50,
833 };
834
835 if rect1.width() {
836 println!("The rectangle has a nonzero width; it is {}", rect1.width);
837 }
838 }
839 ```
840
841 Here, we’re choosing to make the `width` method return `true` if the value in
842 the instance’s `width` field is greater than 0, and `false` if the value is 0:
843 we can use a field within a method of the same name for any purpose. In `main`,
844 when we follow `rect1.width` with parentheses, Rust knows we mean the method
845 `width`. When we don’t use parentheses, Rust knows we mean the field `width`.
846
847 Often, but not always, when we give methods with the same name as a field we
848 want it to only return the value in the field and do nothing else. Methods like
849 this are called *getters*, and Rust does not implement them automatically for
850 struct fields as some other languages do. Getters are useful because you can
851 make the field private but the method public and thus enable read-only access
852 to that field as part of the type’s public API. We will be discussing what
853 public and private are and how to designate a field or method as public or
854 private in Chapter 7.
855
856 > ### Where’s the `->` Operator?
857 >
858 > In C and C++, two different operators are used for calling methods: you use
859 > `.` if you’re calling a method on the object directly and `->` if you’re
860 > calling the method on a pointer to the object and need to dereference the
861 > pointer first. In other words, if `object` is a pointer,
862 > `object->something()` is similar to `(*object).something()`.
863 >
864 > Rust doesn’t have an equivalent to the `->` operator; instead, Rust has a
865 > feature called *automatic referencing and dereferencing*. Calling methods is
866 > one of the few places in Rust that has this behavior.
867 >
868 > Here’s how it works: when you call a method with `object.something()`, Rust
869 > automatically adds in `&`, `&mut`, or `*` so `object` matches the signature of
870 > the method. In other words, the following are the same:
871 >
872 >
873 > ```
874 > p1.distance(&p2);
875 > (&p1).distance(&p2);
876 > ```
877 >
878 > The first one looks much cleaner. This automatic referencing behavior works
879 > because methods have a clear receiver—the type of `self`. Given the receiver
880 > and name of a method, Rust can figure out definitively whether the method is
881 > reading (`&self`), mutating (`&mut self`), or consuming (`self`). The fact
882 > that Rust makes borrowing implicit for method receivers is a big part of
883 > making ownership ergonomic in practice.
884
885 ### Methods with More Parameters
886
887 Let’s practice using methods by implementing a second method on the `Rectangle`
888 struct. This time, we want an instance of `Rectangle` to take another instance
889 of `Rectangle` and return `true` if the second `Rectangle` can fit completely
890 within `self` (the first `Rectangle`); otherwise it should return `false`. That
891 is, once we’ve defined the `can_hold` method, we want to be able to write the
892 program shown in Listing 5-14.
893
894 Filename: src/main.rs
895
896 ```
897 fn main() {
898 let rect1 = Rectangle {
899 width: 30,
900 height: 50,
901 };
902 let rect2 = Rectangle {
903 width: 10,
904 height: 40,
905 };
906 let rect3 = Rectangle {
907 width: 60,
908 height: 45,
909 };
910
911 println!("Can rect1 hold rect2? {}", rect1.can_hold(&rect2));
912 println!("Can rect1 hold rect3? {}", rect1.can_hold(&rect3));
913 }
914 ```
915
916 Listing 5-14: Using the as-yet-unwritten `can_hold` method
917
918 And the expected output would look like the following, because both dimensions
919 of `rect2` are smaller than the dimensions of `rect1` but `rect3` is wider than
920 `rect1`:
921
922 ```
923 Can rect1 hold rect2? true
924 Can rect1 hold rect3? false
925 ```
926
927 We know we want to define a method, so it will be within the `impl Rectangle`
928 block. The method name will be `can_hold`, and it will take an immutable borrow
929 of another `Rectangle` as a parameter. We can tell what the type of the
930 parameter will be by looking at the code that calls the method:
931 `rect1.can_hold(&rect2)` passes in `&rect2`, which is an immutable borrow to
932 `rect2`, an instance of `Rectangle`. This makes sense because we only need to
933 read `rect2` (rather than write, which would mean we’d need a mutable borrow),
934 and we want `main` to retain ownership of `rect2` so we can use it again after
935 calling the `can_hold` method. The return value of `can_hold` will be a
936 Boolean, and the implementation will check whether the width and height of
937 `self` are both greater than the width and height of the other `Rectangle`,
938 respectively. Let’s add the new `can_hold` method to the `impl` block from
939 Listing 5-13, shown in Listing 5-15.
940
941 Filename: src/main.rs
942
943 ```
944 impl Rectangle {
945 fn area(&self) -> u32 {
946 self.width * self.height
947 }
948
949 fn can_hold(&self, other: &Rectangle) -> bool {
950 self.width > other.width && self.height > other.height
951 }
952 }
953 ```
954
955 Listing 5-15: Implementing the `can_hold` method on `Rectangle` that takes
956 another `Rectangle` instance as a parameter
957
958 When we run this code with the `main` function in Listing 5-14, we’ll get our
959 desired output. Methods can take multiple parameters that we add to the
960 signature after the `self` parameter, and those parameters work just like
961 parameters in functions.
962
963 ### Associated Functions
964
965 All functions defined within an `impl` block are called *associated functions*
966 because they’re associated with the type named after the `impl`. We can define
967 associated functions that don’t have `self` as their first parameter (and thus
968 are not methods) because they don’t need an instance of the type to work with.
969 We’ve already used one function like this: the `String::from` function that’s
970 defined on the `String` type.
971
972 Associated functions that aren’t methods are often used for constructors that
973 will return a new instance of the struct. These are often called `new`, but
974 `new` isn’t a special name and isn’t built into the language. For example, we
975 could choose to provide an associated function named `square` that would have
976 one dimension parameter and use that as both width and height, thus making it
977 easier to create a square `Rectangle` rather than having to specify the same
978 value twice:
979
980 Filename: src/main.rs
981
982 ```
983 impl Rectangle {
984 fn square(size: u32) -> Self [1] {
985 Self [2] {
986 width: size,
987 height: size,
988 }
989 }
990 }
991 ```
992
993 The `Self` keywords in the return type [1] and in the body of the function [2]
994 are aliases for the type that appears after the `impl` keyword, which in this
995 case is `Rectangle`.
996
997 To call this associated function, we use the `::` syntax with the struct name;
998 `let sq = Rectangle::square(3);` is an example. This function is namespaced by
999 the struct: the `::` syntax is used for both associated functions and
1000 namespaces created by modules. We’ll discuss modules in Chapter 7.
1001
1002 <!--- Should we mention the most common associated function is `new`? And that
1003 new isn't built into the language.
1004 /JT --->
1005 <!-- I've added a note as such above to the paragraph that starts with
1006 "Associated functions that aren’t methods" /Carol -->
1007
1008 ### Multiple `impl` Blocks
1009
1010 Each struct is allowed to have multiple `impl` blocks. For example, Listing
1011 5-15 is equivalent to the code shown in Listing 5-16, which has each method
1012 in its own `impl` block.
1013
1014 ```
1015 impl Rectangle {
1016 fn area(&self) -> u32 {
1017 self.width * self.height
1018 }
1019 }
1020
1021 impl Rectangle {
1022 fn can_hold(&self, other: &Rectangle) -> bool {
1023 self.width > other.width && self.height > other.height
1024 }
1025 }
1026 ```
1027
1028 Listing 5-16: Rewriting Listing 5-15 using multiple `impl` blocks
1029
1030 There’s no reason to separate these methods into multiple `impl` blocks here,
1031 but this is valid syntax. We’ll see a case in which multiple `impl` blocks are
1032 useful in Chapter 10, where we discuss generic types and traits.
1033
1034 ## Summary
1035
1036 Structs let you create custom types that are meaningful for your domain. By
1037 using structs, you can keep associated pieces of data connected to each other
1038 and name each piece to make your code clear. In `impl` blocks, you can define
1039 functions that are associated with your type, and methods are a kind of
1040 associated function that let you specify the behavior that instances of your
1041 structs have.
1042
1043 But structs aren’t the only way you can create custom types: let’s turn to
1044 Rust’s enum feature to add another tool to your toolbox.
1045
1046 <!--- We don't mention that you can only use `impl` in the same crate as the
1047 type it's created in, otherwise you could use `impl` and add methods on types
1048 that come from other people (which you can't do, unless you make a trait to
1049 attach them to)
1050
1051 Another thing we may want to mention is that `Self` inside of an `impl` refers
1052 to the type being impl'd. So you might write the above:
1053
1054 ```
1055 impl Rectangle {
1056 fn square(size: u32) -> Self {
1057 Self {
1058 width: size,
1059 height: size,
1060 }
1061 }
1062 }
1063 ```
1064 which is often a bit more ergonomic.
1065
1066 /JT --->
1067 <!-- I've changed the `square` example to use `Self` and added some wingdings
1068 and notes explaining that. I don't really want to get into the restrictions on
1069 `impl` on types defined in another crate, because we haven't covered traits
1070 yet. Traits let you do `impl Trait for OtherCrateType` in some circumstances,
1071 so I don't want to say "you can't use an `impl` block on types from other
1072 crates" because I'd have to allude to traits or potentially give the reader the
1073 wrong impression. We get into these restrictions in chapter 10. -->