]> git.proxmox.com Git - rustc.git/blob - src/doc/book/src/ch05-03-method-syntax.md
New upstream version 1.52.0~beta.3+dfsg1
[rustc.git] / src / doc / book / src / ch05-03-method-syntax.md
1 ## Method Syntax
2
3 *Methods* are similar to functions: they’re declared with the `fn` keyword and
4 their name, they can have parameters and a return value, and they contain some
5 code that is run when they’re called from somewhere else. However, methods are
6 different from functions in that they’re defined within the context of a struct
7 (or an enum or a trait object, which we cover in Chapters 6 and 17,
8 respectively), and their first parameter is always `self`, which represents the
9 instance of the struct the method is being called on.
10
11 ### Defining Methods
12
13 Let’s change the `area` function that has a `Rectangle` instance as a parameter
14 and instead make an `area` method defined on the `Rectangle` struct, as shown
15 in Listing 5-13.
16
17 <span class="filename">Filename: src/main.rs</span>
18
19 ```rust
20 {{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-13/src/main.rs}}
21 ```
22
23 <span class="caption">Listing 5-13: Defining an `area` method on the
24 `Rectangle` struct</span>
25
26 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.
41
42 We’ve chosen `&self` here for the same reason we used `&Rectangle` in the
43 function version: we don’t want to take ownership, and we just want to read the
44 data in the struct, not write to it. If we wanted to change the instance that
45 we’ve called the method on as part of what the method does, we’d use `&mut
46 self` as the first parameter. Having a method that takes ownership of the
47 instance by using just `self` as the first parameter is rare; this technique is
48 usually used when the method transforms `self` into something else and you want
49 to prevent the caller from using the original instance after the transformation.
50
51 The main benefit of using methods instead of functions, in addition to using
52 method syntax and not having to repeat the type of `self` in every method’s
53 signature, is for organization. We’ve put all the things we can do with an
54 instance of a type in one `impl` block rather than making future users of our
55 code search for capabilities of `Rectangle` in various places in the library we
56 provide.
57
58 > ### Where’s the `->` Operator?
59 >
60 > In C and C++, two different operators are used for calling methods: you use
61 > `.` if you’re calling a method on the object directly and `->` if you’re
62 > calling the method on a pointer to the object and need to dereference the
63 > pointer first. In other words, if `object` is a pointer,
64 > `object->something()` is similar to `(*object).something()`.
65 >
66 > Rust doesn’t have an equivalent to the `->` operator; instead, Rust has a
67 > feature called *automatic referencing and dereferencing*. Calling methods is
68 > one of the few places in Rust that has this behavior.
69 >
70 > Here’s how it works: when you call a method with `object.something()`, Rust
71 > automatically adds in `&`, `&mut`, or `*` so `object` matches the signature of
72 > the method. In other words, the following are the same:
73 >
74 > <!-- CAN'T EXTRACT SEE BUG https://github.com/rust-lang/mdBook/issues/1127 -->
75 > ```rust
76 > # #[derive(Debug,Copy,Clone)]
77 > # struct Point {
78 > # x: f64,
79 > # y: f64,
80 > # }
81 > #
82 > # impl Point {
83 > # fn distance(&self, other: &Point) -> f64 {
84 > # let x_squared = f64::powi(other.x - self.x, 2);
85 > # let y_squared = f64::powi(other.y - self.y, 2);
86 > #
87 > # f64::sqrt(x_squared + y_squared)
88 > # }
89 > # }
90 > # let p1 = Point { x: 0.0, y: 0.0 };
91 > # let p2 = Point { x: 5.0, y: 6.5 };
92 > p1.distance(&p2);
93 > (&p1).distance(&p2);
94 > ```
95 >
96 > The first one looks much cleaner. This automatic referencing behavior works
97 > because methods have a clear receiver—the type of `self`. Given the receiver
98 > and name of a method, Rust can figure out definitively whether the method is
99 > reading (`&self`), mutating (`&mut self`), or consuming (`self`). The fact
100 > that Rust makes borrowing implicit for method receivers is a big part of
101 > making ownership ergonomic in practice.
102
103 ### Methods with More Parameters
104
105 Let’s practice using methods by implementing a second method on the `Rectangle`
106 struct. This time, we want an instance of `Rectangle` to take another instance
107 of `Rectangle` and return `true` if the second `Rectangle` can fit completely
108 within `self`; otherwise it should return `false`. That is, we want to be able
109 to write the program shown in Listing 5-14, once we’ve defined the `can_hold`
110 method.
111
112 <span class="filename">Filename: src/main.rs</span>
113
114 ```rust,ignore
115 {{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-14/src/main.rs}}
116 ```
117
118 <span class="caption">Listing 5-14: Using the as-yet-unwritten `can_hold`
119 method</span>
120
121 And the expected output would look like the following, because both dimensions
122 of `rect2` are smaller than the dimensions of `rect1` but `rect3` is wider than
123 `rect1`:
124
125 ```text
126 Can rect1 hold rect2? true
127 Can rect1 hold rect3? false
128 ```
129
130 We know we want to define a method, so it will be within the `impl Rectangle`
131 block. The method name will be `can_hold`, and it will take an immutable borrow
132 of another `Rectangle` as a parameter. We can tell what the type of the
133 parameter will be by looking at the code that calls the method:
134 `rect1.can_hold(&rect2)` passes in `&rect2`, which is an immutable borrow to
135 `rect2`, an instance of `Rectangle`. This makes sense because we only need to
136 read `rect2` (rather than write, which would mean we’d need a mutable borrow),
137 and we want `main` to retain ownership of `rect2` so we can use it again after
138 calling the `can_hold` method. The return value of `can_hold` will be a
139 Boolean, and the implementation will check whether the width and height of
140 `self` are both greater than the width and height of the other `Rectangle`,
141 respectively. Let’s add the new `can_hold` method to the `impl` block from
142 Listing 5-13, shown in Listing 5-15.
143
144 <span class="filename">Filename: src/main.rs</span>
145
146 ```rust
147 {{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-15/src/main.rs:here}}
148 ```
149
150 <span class="caption">Listing 5-15: Implementing the `can_hold` method on
151 `Rectangle` that takes another `Rectangle` instance as a parameter</span>
152
153 When we run this code with the `main` function in Listing 5-14, we’ll get our
154 desired output. Methods can take multiple parameters that we add to the
155 signature after the `self` parameter, and those parameters work just like
156 parameters in functions.
157
158 ### Associated Functions
159
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.
166
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:
172
173 <span class="filename">Filename: src/main.rs</span>
174
175 ```rust
176 {{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/no-listing-03-associated-functions/src/main.rs:here}}
177 ```
178
179 To call this associated function, we use the `::` syntax with the struct name;
180 `let sq = Rectangle::square(3);` is an example. This function is namespaced by
181 the struct: the `::` syntax is used for both associated functions and
182 namespaces created by modules. We’ll discuss modules in Chapter 7.
183
184 ### Multiple `impl` Blocks
185
186 Each struct is allowed to have multiple `impl` blocks. For example, Listing
187 5-15 is equivalent to the code shown in Listing 5-16, which has each method
188 in its own `impl` block.
189
190 ```rust
191 {{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-16/src/main.rs:here}}
192 ```
193
194 <span class="caption">Listing 5-16: Rewriting Listing 5-15 using multiple `impl`
195 blocks</span>
196
197 There’s no reason to separate these methods into multiple `impl` blocks here,
198 but this is valid syntax. We’ll see a case in which multiple `impl` blocks are
199 useful in Chapter 10, where we discuss generic types and traits.
200
201 ## Summary
202
203 Structs let you create custom types that are meaningful for your domain. By
204 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.
209
210 But structs aren’t the only way you can create custom types: let’s turn to
211 Rust’s enum feature to add another tool to your toolbox.