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