]>
Commit | Line | Data |
---|---|---|
2c00a5a8 XL |
1 | # Traits |
2 | ||
3 | A `trait` is a collection of methods defined for an unknown type: | |
4 | `Self`. They can access other methods declared in the same trait. | |
5 | ||
6 | Traits can be implemented for any data type. In the example below, | |
7 | we define `Animal`, a group of methods. The `Animal` `trait` is | |
8 | then implemented for the `Sheep` data type, allowing the use of | |
9 | methods from `Animal` with a `Sheep`. | |
10 | ||
11 | ```rust,editable | |
12 | struct Sheep { naked: bool, name: &'static str } | |
13 | ||
14 | trait Animal { | |
15 | // Static method signature; `Self` refers to the implementor type. | |
16 | fn new(name: &'static str) -> Self; | |
17 | ||
18 | // Instance method signatures; these will return a string. | |
19 | fn name(&self) -> &'static str; | |
20 | fn noise(&self) -> &'static str; | |
21 | ||
22 | // Traits can provide default method definitions. | |
23 | fn talk(&self) { | |
24 | println!("{} says {}", self.name(), self.noise()); | |
25 | } | |
26 | } | |
27 | ||
28 | impl Sheep { | |
29 | fn is_naked(&self) -> bool { | |
30 | self.naked | |
31 | } | |
32 | ||
33 | fn shear(&mut self) { | |
34 | if self.is_naked() { | |
35 | // Implementor methods can use the implementor's trait methods. | |
36 | println!("{} is already naked...", self.name()); | |
37 | } else { | |
38 | println!("{} gets a haircut!", self.name); | |
39 | ||
40 | self.naked = true; | |
41 | } | |
42 | } | |
43 | } | |
44 | ||
45 | // Implement the `Animal` trait for `Sheep`. | |
46 | impl Animal for Sheep { | |
47 | // `Self` is the implementor type: `Sheep`. | |
48 | fn new(name: &'static str) -> Sheep { | |
49 | Sheep { name: name, naked: false } | |
50 | } | |
51 | ||
52 | fn name(&self) -> &'static str { | |
53 | self.name | |
54 | } | |
55 | ||
56 | fn noise(&self) -> &'static str { | |
57 | if self.is_naked() { | |
58 | "baaaaah?" | |
59 | } else { | |
60 | "baaaaah!" | |
61 | } | |
62 | } | |
63 | ||
64 | // Default trait methods can be overridden. | |
65 | fn talk(&self) { | |
66 | // For example, we can add some quiet contemplation. | |
67 | println!("{} pauses briefly... {}", self.name, self.noise()); | |
68 | } | |
69 | } | |
70 | ||
71 | fn main() { | |
72 | // Type annotation is necessary in this case. | |
73 | let mut dolly: Sheep = Animal::new("Dolly"); | |
74 | // TODO ^ Try removing the type annotations. | |
75 | ||
76 | dolly.talk(); | |
77 | dolly.shear(); | |
78 | dolly.talk(); | |
79 | } | |
80 | ``` |