]> git.lizzy.rs Git - rust.git/blob - src/doc/trpl/method-syntax.md
Resolve unused_parens compilation warning
[rust.git] / src / doc / trpl / method-syntax.md
1 % Method Syntax
2
3 Functions are great, but if you want to call a bunch of them on some data, it
4 can be awkward. Consider this code:
5
6 ```rust,ignore
7 baz(bar(foo));
8 ```
9
10 We would read this left-to-right, and so we see ‘baz bar foo’. But this isn’t the
11 order that the functions would get called in, that’s inside-out: ‘foo bar baz’.
12 Wouldn’t it be nice if we could do this instead?
13
14 ```rust,ignore
15 foo.bar().baz();
16 ```
17
18 Luckily, as you may have guessed with the leading question, you can! Rust provides
19 the ability to use this ‘method call syntax’ via the `impl` keyword.
20
21 # Method calls
22
23 Here’s how it works:
24
25 ```rust
26 struct Circle {
27     x: f64,
28     y: f64,
29     radius: f64,
30 }
31
32 impl Circle {
33     fn area(&self) -> f64 {
34         std::f64::consts::PI * (self.radius * self.radius)
35     }
36 }
37
38 fn main() {
39     let c = Circle { x: 0.0, y: 0.0, radius: 2.0 };
40     println!("{}", c.area());
41 }
42 ```
43
44 This will print `12.566371`.
45
46
47
48 We’ve made a `struct` that represents a circle. We then write an `impl` block,
49 and inside it, define a method, `area`.
50
51 Methods take a special first parameter, of which there are three variants:
52 `self`, `&self`, and `&mut self`. You can think of this first parameter as
53 being the `foo` in `foo.bar()`. The three variants correspond to the three
54 kinds of things `foo` could be: `self` if it’s just a value on the stack,
55 `&self` if it’s a reference, and `&mut self` if it’s a mutable reference.
56 Because we took the `&self` parameter to `area`, we can use it just like any
57 other parameter. Because we know it’s a `Circle`, we can access the `radius`
58 just like we would with any other `struct`. 
59
60 We should default to using `&self`, as you should prefer borrowing over taking
61 ownership, as well as taking immutable references over mutable ones. Here’s an
62 example of all three variants:
63
64 ```rust
65 struct Circle {
66     x: f64,
67     y: f64,
68     radius: f64,
69 }
70
71 impl Circle {
72     fn reference(&self) {
73        println!("taking self by reference!");
74     }
75
76     fn mutable_reference(&mut self) {
77        println!("taking self by mutable reference!");
78     }
79
80     fn takes_ownership(self) {
81        println!("taking ownership of self!");
82     }
83 }
84 ```
85
86 # Chaining method calls
87
88 So, now we know how to call a method, such as `foo.bar()`. But what about our
89 original example, `foo.bar().baz()`? This is called ‘method chaining’. Let’s
90 look at an example:
91
92 ```rust
93 struct Circle {
94     x: f64,
95     y: f64,
96     radius: f64,
97 }
98
99 impl Circle {
100     fn area(&self) -> f64 {
101         std::f64::consts::PI * (self.radius * self.radius)
102     }
103
104     fn grow(&self, increment: f64) -> Circle {
105         Circle { x: self.x, y: self.y, radius: self.radius + increment }
106     }
107 }
108
109 fn main() {
110     let c = Circle { x: 0.0, y: 0.0, radius: 2.0 };
111     println!("{}", c.area());
112
113     let d = c.grow(2.0).area();
114     println!("{}", d);
115 }
116 ```
117
118 Check the return type:
119
120 ```rust
121 # struct Circle;
122 # impl Circle {
123 fn grow(&self, increment: f64) -> Circle {
124 # Circle } }
125 ```
126
127 We just say we’re returning a `Circle`. With this method, we can grow a new
128 `Circle` to any arbitrary size.
129
130 # Associated functions
131
132 You can also define associated functions that do not take a `self` parameter.
133 Here’s a pattern that’s very common in Rust code:
134
135 ```rust
136 struct Circle {
137     x: f64,
138     y: f64,
139     radius: f64,
140 }
141
142 impl Circle {
143     fn new(x: f64, y: f64, radius: f64) -> Circle {
144         Circle {
145             x: x,
146             y: y,
147             radius: radius,
148         }
149     }
150 }
151
152 fn main() {
153     let c = Circle::new(0.0, 0.0, 2.0);
154 }
155 ```
156
157 This ‘associated function’ builds a new `Circle` for us. Note that associated
158 functions are called with the `Struct::function()` syntax, rather than the
159 `ref.method()` syntax. Some other languages call associated functions ‘static
160 methods’.
161
162 # Builder Pattern
163
164 Let’s say that we want our users to be able to create `Circle`s, but we will
165 allow them to only set the properties they care about. Otherwise, the `x`
166 and `y` attributes will be `0.0`, and the `radius` will be `1.0`. Rust doesn’t
167 have method overloading, named arguments, or variable arguments. We employ
168 the builder pattern instead. It looks like this:
169
170 ```rust
171 struct Circle {
172     x: f64,
173     y: f64,
174     radius: f64,
175 }
176
177 impl Circle {
178     fn area(&self) -> f64 {
179         std::f64::consts::PI * (self.radius * self.radius)
180     }
181 }
182
183 struct CircleBuilder {
184     x: f64,
185     y: f64,
186     radius: f64,
187 }
188
189 impl CircleBuilder {
190     fn new() -> CircleBuilder {
191         CircleBuilder { x: 0.0, y: 0.0, radius: 1.0, }
192     }
193
194     fn x(&mut self, coordinate: f64) -> &mut CircleBuilder {
195         self.x = coordinate;
196         self
197     }
198
199     fn y(&mut self, coordinate: f64) -> &mut CircleBuilder {
200         self.y = coordinate;
201         self
202     }
203
204     fn radius(&mut self, radius: f64) -> &mut CircleBuilder {
205         self.radius = radius;
206         self
207     }
208
209     fn finalize(&self) -> Circle {
210         Circle { x: self.x, y: self.y, radius: self.radius }
211     }
212 }
213
214 fn main() {
215     let c = CircleBuilder::new()
216                 .x(1.0)
217                 .y(2.0)
218                 .radius(2.0)
219                 .finalize();
220
221     println!("area: {}", c.area());
222     println!("x: {}", c.x);
223     println!("y: {}", c.y);
224 }
225 ```
226
227 What we’ve done here is make another `struct`, `CircleBuilder`. We’ve defined our
228 builder methods on it. We’ve also defined our `area()` method on `Circle`. We
229 also made one more method on `CircleBuilder`: `finalize()`. This method creates
230 our final `Circle` from the builder. Now, we’ve used the type system to enforce
231 our concerns: we can use the methods on `CircleBuilder` to constrain making
232 `Circle`s in any way we choose.