@@ -18,6 +18,8 @@ x.foo().bar().baz();
1818Luckily, as you may have guessed with the leading question, you can! Rust provides
1919the ability to use this * method call syntax* via the ` impl ` keyword.
2020
21+ ## Method calls
22+
2123Here'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`
5658just like we would with any other struct. An import of π and some
5759multiplications 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+
59107You can also define methods that do not take a ` self ` parameter. Here's a
60108pattern that's very common in Rust code:
61109
62- ``` {rust}
63- # #![allow(non_shorthand_field_patterns)]
110+ ```
64111struct Circle {
65112 x: f64,
66113 y: f64,
@@ -86,3 +133,66 @@ This *static method* builds a new `Circle` for us. Note that static methods
86133are called with the ` Struct::method() ` syntax, rather than the ` ref.method() `
87134syntax.
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