Skip to content

Commit aca7939

Browse files
committed
Soup up 'method syntax' chapter of the Book
Fixes rust-lang#16969
1 parent b7930d9 commit aca7939

File tree

1 file changed

+112
-2
lines changed

1 file changed

+112
-2
lines changed

src/doc/trpl/method-syntax.md

+112-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ x.foo().bar().baz();
1818
Luckily, as you may have guessed with the leading question, you can! Rust provides
1919
the ability to use this *method call syntax* via the `impl` keyword.
2020

21+
## Method calls
22+
2123
Here's how it works:
2224

2325
```{rust}
@@ -56,11 +58,56 @@ other parameter. Because we know it's a `Circle`, we can access the `radius`
5658
just like we would with any other struct. An import of π and some
5759
multiplications later, and we have our area.
5860

61+
## Chaining method calls
62+
63+
So, now we know how to call a method, such as `foo.bar()`. But what about our
64+
original example, `foo.bar().baz()`? This is called 'method chaining', and we
65+
can do it by returning `self`.
66+
67+
```
68+
struct Circle {
69+
x: f64,
70+
y: f64,
71+
radius: f64,
72+
}
73+
74+
impl Circle {
75+
fn area(&self) -> f64 {
76+
std::f64::consts::PI * (self.radius * self.radius)
77+
}
78+
79+
fn grow(&self) -> Circle {
80+
Circle { x: self.x, y: self.y, radius: (self.radius * 10.0) }
81+
}
82+
}
83+
84+
fn main() {
85+
let c = Circle { x: 0.0, y: 0.0, radius: 2.0 };
86+
println!("{}", c.area());
87+
88+
let d = c.grow().area();
89+
println!("{}", d);
90+
}
91+
```
92+
93+
Check the return type:
94+
95+
```
96+
# struct Circle;
97+
# impl Circle {
98+
fn grow(&self) -> Circle {
99+
# Circle } }
100+
```
101+
102+
We just say we're returning a `Circle`. With this, we can grow a new circle
103+
that's twice as big as the old one.
104+
105+
## Static methods
106+
59107
You can also define methods that do not take a `self` parameter. Here's a
60108
pattern that's very common in Rust code:
61109

62-
```{rust}
63-
# #![allow(non_shorthand_field_patterns)]
110+
```
64111
struct Circle {
65112
x: f64,
66113
y: f64,
@@ -86,3 +133,66 @@ This *static method* builds a new `Circle` for us. Note that static methods
86133
are called with the `Struct::method()` syntax, rather than the `ref.method()`
87134
syntax.
88135

136+
## Builder Pattern
137+
138+
Let's say that we want our users to be able to create Circles, but we will
139+
allow them to only set the properties they care about. Otherwise, the `x`
140+
and `y` attributes will be `0.0`, and the `radius` will be `1.0`. Rust doesn't
141+
have method overloading, named arguments, or variable arguments. We employ
142+
the builder pattern instead. It looks like this:
143+
144+
```
145+
struct Circle {
146+
x: f64,
147+
y: f64,
148+
radius: f64,
149+
}
150+
151+
impl Circle {
152+
fn area(&self) -> f64 {
153+
std::f64::consts::PI * (self.radius * self.radius)
154+
}
155+
}
156+
157+
struct CircleBuilder {
158+
coordinate: f64,
159+
radius: f64,
160+
}
161+
162+
impl CircleBuilder {
163+
fn new() -> CircleBuilder {
164+
CircleBuilder { coordinate: 0.0, radius: 0.0, }
165+
}
166+
167+
fn coordinate(&mut self, coordinate: f64) -> &mut CircleBuilder {
168+
self.coordinate = coordinate;
169+
self
170+
}
171+
172+
fn radius(&mut self, radius: f64) -> &mut CircleBuilder {
173+
self.radius = radius;
174+
self
175+
}
176+
177+
fn finalize(&self) -> Circle {
178+
Circle { x: self.coordinate, y: self.coordinate, radius: self.radius }
179+
}
180+
}
181+
182+
fn main() {
183+
let c = CircleBuilder::new()
184+
.coordinate(10.0)
185+
.radius(5.0)
186+
.finalize();
187+
188+
189+
println!("area: {}", c.area());
190+
}
191+
```
192+
193+
What we've done here is make another struct, `CircleBuilder`. We've defined our
194+
builder methods on it. We've also defined our `area()` method on `Circle`. We
195+
also made one more method on `CircleBuilder`: `finalize()`. This method creates
196+
our final `Circle` from the builder. Now, we've used the type system to enforce
197+
our concerns: we can use the methods on `CircleBuilder` to constrain making
198+
`Circle`s in any way we choose.

0 commit comments

Comments
 (0)