]>
Commit | Line | Data |
---|---|---|
ea8adc8c XL |
1 | # Implementations |
2 | ||
ff7c6d11 XL |
3 | An _implementation_ is an item that associates items with an *implementing type*. |
4 | ||
5 | There are two types of implementations: inherent implementations and [trait] | |
6 | implementations. | |
ea8adc8c XL |
7 | |
8 | Implementations are defined with the keyword `impl`. | |
9 | ||
ff7c6d11 XL |
10 | ## Interent Implementations |
11 | ||
12 | An inherent implementation is defined as the sequence of the `impl` keyword, | |
13 | generic type declarations, a path to a nomial type, a where clause, and a | |
14 | bracketed set of associable items. | |
15 | ||
16 | The nominal type is called the *implementing type* and the associable items are | |
17 | the *associated items* to the implementing type. | |
18 | ||
19 | Inherent implementations associate the associated items to the implementing | |
20 | type. | |
21 | ||
22 | The associated item has a path of a path to the implementing type followed by | |
23 | the associate item's path component. | |
24 | ||
25 | Inherent implementations cannot contain associated type aliases. | |
26 | ||
27 | A type can have multiple inherent implementations. | |
28 | ||
29 | The implementing type must be defined within the same crate. | |
30 | ||
31 | ```rust | |
32 | struct Point {x: i32, y: i32} | |
33 | ||
34 | impl Point { | |
35 | fn log(&self) { | |
36 | println!("Point is at ({}, {})", self.x, self.y); | |
37 | } | |
38 | } | |
39 | ||
40 | let my_point = Point {x: 10, y:11}; | |
41 | my_point.log(); | |
42 | ``` | |
43 | ||
44 | ## Trait Implementations | |
45 | ||
46 | A *trait implementation* is defined like an inherent implementation except that | |
47 | the optional generic type declarations is followed by a [trait] followed | |
48 | by the keyword `for`. <!-- To understand this, you have to back-reference to | |
49 | the previous section. :( --> | |
50 | ||
51 | The trait is known as the *implemented trait*. | |
52 | ||
53 | The implementing type implements the implemented trait. | |
54 | ||
55 | A trait implementation must define all non-default associated items declared | |
56 | by the implemented trait, may redefine default associated items defined by the | |
57 | implemented trait trait, and cannot define any other items. | |
58 | ||
59 | The path to the associated items is `<` followed by a path to the implementing | |
60 | type followed by `as` followed by a path to the trait followed by `>` as a path | |
61 | component followed by the associated item's path component. | |
62 | ||
ea8adc8c XL |
63 | ```rust |
64 | # #[derive(Copy, Clone)] | |
65 | # struct Point {x: f64, y: f64}; | |
66 | # type Surface = i32; | |
67 | # struct BoundingBox {x: f64, y: f64, width: f64, height: f64}; | |
68 | # trait Shape { fn draw(&self, Surface); fn bounding_box(&self) -> BoundingBox; } | |
69 | # fn do_draw_circle(s: Surface, c: Circle) { } | |
70 | struct Circle { | |
71 | radius: f64, | |
72 | center: Point, | |
73 | } | |
74 | ||
75 | impl Copy for Circle {} | |
76 | ||
77 | impl Clone for Circle { | |
78 | fn clone(&self) -> Circle { *self } | |
79 | } | |
80 | ||
81 | impl Shape for Circle { | |
82 | fn draw(&self, s: Surface) { do_draw_circle(s, *self); } | |
83 | fn bounding_box(&self) -> BoundingBox { | |
84 | let r = self.radius; | |
85 | BoundingBox { | |
86 | x: self.center.x - r, | |
87 | y: self.center.y - r, | |
88 | width: 2.0 * r, | |
89 | height: 2.0 * r, | |
90 | } | |
91 | } | |
92 | } | |
93 | ``` | |
94 | ||
ff7c6d11 | 95 | ### Trait Implementation Coherence |
ea8adc8c | 96 | |
ff7c6d11 XL |
97 | A trait implementation is consider incoherent if either the orphan check fails |
98 | or there are overlapping implementation instaces. | |
ea8adc8c | 99 | |
ff7c6d11 XL |
100 | Two trait implementations overlap when there is a non-empty intersection of the |
101 | traits the implementation is for, the implementations can be instantiated with | |
102 | the same type. <!-- This is probably wrong? Source: No two implementations can | |
103 | be instantiable with the same set of types for the input type parameters. --> | |
ea8adc8c | 104 | |
ff7c6d11 XL |
105 | The `Orphan Check` states that every trait implementation must meet either of |
106 | the following conditions: | |
ea8adc8c | 107 | |
ff7c6d11 XL |
108 | 1. The trait being implemented is defined in the same crate. |
109 | ||
110 | 2. At least one of either `Self` or a generic type parameter of the trait must | |
111 | meet the following grammar, where `C` is a nominal type defined | |
112 | within the containing crate: | |
113 | ||
114 | ```ignore | |
115 | T = C | |
116 | | &T | |
117 | | &mut T | |
118 | | Box<T> | |
119 | ``` | |
120 | ||
121 | ## Generic Implementations | |
ea8adc8c XL |
122 | |
123 | An implementation can take type and lifetime parameters, which can be used in | |
124 | the rest of the implementation. Type parameters declared for an implementation | |
ff7c6d11 XL |
125 | must be used at least once in either the trait or the implementing type of an |
126 | implementation. Implementation parameters are written directly after the `impl` | |
127 | keyword. | |
ea8adc8c XL |
128 | |
129 | ```rust | |
130 | # trait Seq<T> { fn dummy(&self, _: T) { } } | |
131 | impl<T> Seq<T> for Vec<T> { | |
132 | /* ... */ | |
133 | } | |
134 | impl Seq<bool> for u32 { | |
135 | /* Treat the integer as a sequence of bits */ | |
136 | } | |
137 | ``` | |
ff7c6d11 XL |
138 | |
139 | ||
140 | [trait]: items/traits.html |