]> git.lizzy.rs Git - rust.git/blob - src/doc/trpl/method-syntax.md
TRPL: Add `rust` Marker to Some Code Block
[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’, and we
90 can do it by returning `self`.
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) -> 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 Circles, 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.