]>
Commit | Line | Data |
---|---|---|
2c00a5a8 XL |
1 | # The Problem |
2 | ||
3 | A `trait` that is generic over its container type has type specification | |
4 | requirements - users of the `trait` *must* specify all of its generic types. | |
5 | ||
6 | In the example below, the `Contains` `trait` allows the use of the generic | |
7 | types `A` and `B`. The trait is then implemented for the `Container` type, | |
8 | specifying `i32` for `A` and `B` so that it can be used with `fn difference()`. | |
9 | ||
10 | Because `Contains` is generic, we are forced to explicitly state *all* of the | |
11 | generic types for `fn difference()`. In practice, we want a way to express that | |
12 | `A` and `B` are determined by the *input* `C`. As you will see in the next | |
13 | section, associated types provide exactly that capability. | |
14 | ||
15 | ```rust,editable | |
16 | struct Container(i32, i32); | |
17 | ||
18 | // A trait which checks if 2 items are stored inside of container. | |
19 | // Also retrieves first or last value. | |
20 | trait Contains<A, B> { | |
532ac7d7 | 21 | fn contains(&self, _: &A, _: &B) -> bool; // Explicitly requires `A` and `B`. |
2c00a5a8 XL |
22 | fn first(&self) -> i32; // Doesn't explicitly require `A` or `B`. |
23 | fn last(&self) -> i32; // Doesn't explicitly require `A` or `B`. | |
24 | } | |
25 | ||
26 | impl Contains<i32, i32> for Container { | |
27 | // True if the numbers stored are equal. | |
28 | fn contains(&self, number_1: &i32, number_2: &i32) -> bool { | |
29 | (&self.0 == number_1) && (&self.1 == number_2) | |
30 | } | |
31 | ||
32 | // Grab the first number. | |
33 | fn first(&self) -> i32 { self.0 } | |
34 | ||
35 | // Grab the last number. | |
36 | fn last(&self) -> i32 { self.1 } | |
37 | } | |
38 | ||
39 | // `C` contains `A` and `B`. In light of that, having to express `A` and | |
40 | // `B` again is a nuisance. | |
41 | fn difference<A, B, C>(container: &C) -> i32 where | |
42 | C: Contains<A, B> { | |
43 | container.last() - container.first() | |
44 | } | |
45 | ||
46 | fn main() { | |
47 | let number_1 = 3; | |
48 | let number_2 = 10; | |
49 | ||
50 | let container = Container(number_1, number_2); | |
51 | ||
52 | println!("Does container contain {} and {}: {}", | |
53 | &number_1, &number_2, | |
54 | container.contains(&number_1, &number_2)); | |
55 | println!("First number: {}", container.first()); | |
56 | println!("Last number: {}", container.last()); | |
57 | ||
58 | println!("The difference is: {}", difference(&container)); | |
59 | } | |
60 | ``` | |
61 | ||
62 | ### See also: | |
63 | ||
64 | [`struct`s][structs], and [`trait`s][traits] | |
65 | ||
66 | [structs]: custom_types/structs.html | |
67 | [traits]: trait.html |