]> git.proxmox.com Git - rustc.git/blame - 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
CommitLineData
13cf67c4
XL
1## Method Syntax
2
3*Methods* are similar to functions: they’re declared with the `fn` keyword and
4their name, they can have parameters and a return value, and they contain some
5code that is run when they’re called from somewhere else. However, methods are
6different 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,
8respectively), and their first parameter is always `self`, which represents the
9instance of the struct the method is being called on.
10
11### Defining Methods
12
13Let’s change the `area` function that has a `Rectangle` instance as a parameter
14and instead make an `area` method defined on the `Rectangle` struct, as shown
69743fb6 15in Listing 5-13.
13cf67c4
XL
16
17<span class="filename">Filename: src/main.rs</span>
18
19```rust
74b04a01 20{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-13/src/main.rs}}
13cf67c4
XL
21```
22
23<span class="caption">Listing 5-13: Defining an `area` method on the
24`Rectangle` struct</span>
25
26To define the function within the context of `Rectangle`, we start an `impl`
27(implementation) block. Then we move the `area` function within the `impl`
28curly 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
30called the `area` function and passed `rect1` as an argument, we can instead
31use *method syntax* to call the `area` method on our `Rectangle` instance.
32The method syntax goes after an instance: we add a dot followed by the method
33name, parentheses, and any arguments.
34
35In the signature for `area`, we use `&self` instead of `rectangle: &Rectangle`
36because Rust knows the type of `self` is `Rectangle` due to this method’s being
37inside the `impl Rectangle` context. Note that we still need to use the `&`
38before `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,
40just as they can any other parameter.
41
42We’ve chosen `&self` here for the same reason we used `&Rectangle` in the
43function version: we don’t want to take ownership, and we just want to read the
44data in the struct, not write to it. If we wanted to change the instance that
45we’ve called the method on as part of what the method does, we’d use `&mut
46self` as the first parameter. Having a method that takes ownership of the
47instance by using just `self` as the first parameter is rare; this technique is
48usually used when the method transforms `self` into something else and you want
49to prevent the caller from using the original instance after the transformation.
50
51The main benefit of using methods instead of functions, in addition to using
52method syntax and not having to repeat the type of `self` in every method’s
53signature, is for organization. We’ve put all the things we can do with an
54instance of a type in one `impl` block rather than making future users of our
55code search for capabilities of `Rectangle` in various places in the library we
56provide.
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>
6a06907d 74> <!-- CAN'T EXTRACT SEE BUG https://github.com/rust-lang/mdBook/issues/1127 -->
13cf67c4
XL
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
105Let’s practice using methods by implementing a second method on the `Rectangle`
106struct. This time, we want an instance of `Rectangle` to take another instance
107of `Rectangle` and return `true` if the second `Rectangle` can fit completely
108within `self`; otherwise it should return `false`. That is, we want to be able
109to write the program shown in Listing 5-14, once we’ve defined the `can_hold`
69743fb6 110method.
13cf67c4
XL
111
112<span class="filename">Filename: src/main.rs</span>
113
114```rust,ignore
74b04a01 115{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-14/src/main.rs}}
13cf67c4
XL
116```
117
118<span class="caption">Listing 5-14: Using the as-yet-unwritten `can_hold`
119method</span>
120
121And the expected output would look like the following, because both dimensions
122of `rect2` are smaller than the dimensions of `rect1` but `rect3` is wider than
123`rect1`:
124
125```text
126Can rect1 hold rect2? true
127Can rect1 hold rect3? false
128```
129
130We know we want to define a method, so it will be within the `impl Rectangle`
131block. The method name will be `can_hold`, and it will take an immutable borrow
132of another `Rectangle` as a parameter. We can tell what the type of the
133parameter 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
136read `rect2` (rather than write, which would mean we’d need a mutable borrow),
137and we want `main` to retain ownership of `rect2` so we can use it again after
138calling the `can_hold` method. The return value of `can_hold` will be a
139Boolean, 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`,
141respectively. Let’s add the new `can_hold` method to the `impl` block from
69743fb6 142Listing 5-13, shown in Listing 5-15.
13cf67c4
XL
143
144<span class="filename">Filename: src/main.rs</span>
145
146```rust
74b04a01 147{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-15/src/main.rs:here}}
13cf67c4
XL
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
153When we run this code with the `main` function in Listing 5-14, we’ll get our
154desired output. Methods can take multiple parameters that we add to the
155signature after the `self` parameter, and those parameters work just like
156parameters in functions.
157
158### Associated Functions
159
160Another useful feature of `impl` blocks is that we’re allowed to define
161functions within `impl` blocks that *don’t* take `self` as a parameter. These
162are called *associated functions* because they’re associated with the struct.
163They’re still functions, not methods, because they don’t have an instance of
164the struct to work with. You’ve already used the `String::from` associated
165function.
166
167Associated functions are often used for constructors that will return a new
168instance of the struct. For example, we could provide an associated function
169that would have one dimension parameter and use that as both width and height,
170thus making it easier to create a square `Rectangle` rather than having to
171specify the same value twice:
172
173<span class="filename">Filename: src/main.rs</span>
174
175```rust
74b04a01 176{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/no-listing-03-associated-functions/src/main.rs:here}}
13cf67c4
XL
177```
178
179To 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
181the struct: the `::` syntax is used for both associated functions and
182namespaces created by modules. We’ll discuss modules in Chapter 7.
183
184### Multiple `impl` Blocks
185
186Each struct is allowed to have multiple `impl` blocks. For example, Listing
1875-15 is equivalent to the code shown in Listing 5-16, which has each method
69743fb6 188in its own `impl` block.
13cf67c4
XL
189
190```rust
74b04a01 191{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-16/src/main.rs:here}}
13cf67c4
XL
192```
193
194<span class="caption">Listing 5-16: Rewriting Listing 5-15 using multiple `impl`
195blocks</span>
196
197There’s no reason to separate these methods into multiple `impl` blocks here,
198but this is valid syntax. We’ll see a case in which multiple `impl` blocks are
69743fb6 199useful in Chapter 10, where we discuss generic types and traits.
13cf67c4
XL
200
201## Summary
202
203Structs let you create custom types that are meaningful for your domain. By
204using structs, you can keep associated pieces of data connected to each other
205and name each piece to make your code clear. Methods let you specify the
206behavior that instances of your structs have, and associated functions let you
207namespace functionality that is particular to your struct without having an
208instance available.
209
210But structs aren’t the only way you can create custom types: let’s turn to
211Rust’s enum feature to add another tool to your toolbox.