]>
Commit | Line | Data |
---|---|---|
136023e0 | 1 | # Associated functions & Methods |
2c00a5a8 | 2 | |
136023e0 XL |
3 | Some functions are connected to a particular type. These come in two forms: |
4 | associated functions, and methods. Associated functions are functions that | |
5 | are defined on a type generally, while methods are associated functions that are | |
6 | called on a particular instance of a type. | |
2c00a5a8 XL |
7 | |
8 | ```rust,editable | |
9 | struct Point { | |
10 | x: f64, | |
11 | y: f64, | |
12 | } | |
13 | ||
136023e0 | 14 | // Implementation block, all `Point` associated functions & methods go in here |
2c00a5a8 | 15 | impl Point { |
136023e0 XL |
16 | // This is an "associated function" because this function is associated with |
17 | // a particular type, that is, Point. | |
18 | // | |
19 | // Associated functions don't need to be called with an instance. | |
20 | // These functions are generally used like constructors. | |
2c00a5a8 XL |
21 | fn origin() -> Point { |
22 | Point { x: 0.0, y: 0.0 } | |
23 | } | |
24 | ||
136023e0 | 25 | // Another associated function, taking two arguments: |
2c00a5a8 XL |
26 | fn new(x: f64, y: f64) -> Point { |
27 | Point { x: x, y: y } | |
28 | } | |
29 | } | |
30 | ||
31 | struct Rectangle { | |
32 | p1: Point, | |
33 | p2: Point, | |
34 | } | |
35 | ||
36 | impl Rectangle { | |
136023e0 | 37 | // This is a method |
2c00a5a8 XL |
38 | // `&self` is sugar for `self: &Self`, where `Self` is the type of the |
39 | // caller object. In this case `Self` = `Rectangle` | |
40 | fn area(&self) -> f64 { | |
41 | // `self` gives access to the struct fields via the dot operator | |
42 | let Point { x: x1, y: y1 } = self.p1; | |
43 | let Point { x: x2, y: y2 } = self.p2; | |
44 | ||
45 | // `abs` is a `f64` method that returns the absolute value of the | |
46 | // caller | |
47 | ((x1 - x2) * (y1 - y2)).abs() | |
48 | } | |
49 | ||
50 | fn perimeter(&self) -> f64 { | |
51 | let Point { x: x1, y: y1 } = self.p1; | |
52 | let Point { x: x2, y: y2 } = self.p2; | |
53 | ||
54 | 2.0 * ((x1 - x2).abs() + (y1 - y2).abs()) | |
55 | } | |
56 | ||
57 | // This method requires the caller object to be mutable | |
58 | // `&mut self` desugars to `self: &mut Self` | |
59 | fn translate(&mut self, x: f64, y: f64) { | |
60 | self.p1.x += x; | |
61 | self.p2.x += x; | |
62 | ||
63 | self.p1.y += y; | |
64 | self.p2.y += y; | |
65 | } | |
66 | } | |
67 | ||
68 | // `Pair` owns resources: two heap allocated integers | |
69 | struct Pair(Box<i32>, Box<i32>); | |
70 | ||
71 | impl Pair { | |
72 | // This method "consumes" the resources of the caller object | |
73 | // `self` desugars to `self: Self` | |
74 | fn destroy(self) { | |
75 | // Destructure `self` | |
76 | let Pair(first, second) = self; | |
77 | ||
78 | println!("Destroying Pair({}, {})", first, second); | |
79 | ||
80 | // `first` and `second` go out of scope and get freed | |
81 | } | |
82 | } | |
83 | ||
84 | fn main() { | |
85 | let rectangle = Rectangle { | |
136023e0 | 86 | // Associated functions are called using double colons |
2c00a5a8 XL |
87 | p1: Point::origin(), |
88 | p2: Point::new(3.0, 4.0), | |
89 | }; | |
90 | ||
136023e0 | 91 | // Methods are called using the dot operator |
2c00a5a8 XL |
92 | // Note that the first argument `&self` is implicitly passed, i.e. |
93 | // `rectangle.perimeter()` === `Rectangle::perimeter(&rectangle)` | |
94 | println!("Rectangle perimeter: {}", rectangle.perimeter()); | |
95 | println!("Rectangle area: {}", rectangle.area()); | |
96 | ||
97 | let mut square = Rectangle { | |
98 | p1: Point::origin(), | |
99 | p2: Point::new(1.0, 1.0), | |
100 | }; | |
101 | ||
102 | // Error! `rectangle` is immutable, but this method requires a mutable | |
103 | // object | |
104 | //rectangle.translate(1.0, 0.0); | |
105 | // TODO ^ Try uncommenting this line | |
106 | ||
107 | // Okay! Mutable objects can call mutable methods | |
108 | square.translate(1.0, 1.0); | |
109 | ||
110 | let pair = Pair(Box::new(1), Box::new(2)); | |
111 | ||
112 | pair.destroy(); | |
113 | ||
114 | // Error! Previous `destroy` call "consumed" `pair` | |
115 | //pair.destroy(); | |
116 | // TODO ^ Try uncommenting this line | |
117 | } | |
136023e0 | 118 | ``` |