@@ -4,46 +4,54 @@ minutes: 10
4
4
5
5
# Generic Data Types
6
6
7
- You can use generics to abstract over the concrete field type:
7
+ You can use generics to abstract over the concrete field type. Returning to the
8
+ exercise for the previous segment:
8
9
9
10
``` rust,editable
10
- #[derive(Debug)]
11
- struct Point<T> {
12
- x: T,
13
- y: T,
11
+ pub trait Logger {
12
+ /// Log a message at the given verbosity level.
13
+ fn log(&self, verbosity: u8, message: &str);
14
14
}
15
15
16
- impl<T> Point<T> {
17
- fn coords(&self) -> (&T, &T) {
18
- (&self.x, &self.y)
16
+ struct StderrLogger;
17
+
18
+ impl Logger for StderrLogger {
19
+ fn log(&self, verbosity: u8, message: &str) {
20
+ eprintln!("verbosity={verbosity}: {message}");
19
21
}
22
+ }
23
+
24
+ /// Only log messages up to the given verbosity level.
25
+ struct VerbosityFilter<L: Logger> {
26
+ max_verbosity: u8,
27
+ inner: L,
28
+ }
20
29
21
- fn set_x(&mut self, x: T) {
22
- self.x = x;
30
+ impl<L: Logger> Logger for VerbosityFilter<L> {
31
+ fn log(&self, verbosity: u8, message: &str) {
32
+ if verbosity <= self.max_verbosity {
33
+ self.inner.log(verbosity, message);
34
+ }
23
35
}
24
36
}
25
37
26
38
fn main() {
27
- let integer = Point { x: 5, y: 10 };
28
- let float = Point { x: 1.0, y: 4.0 };
29
- println!("{integer:?} and {float:?}");
30
- println!("coords: {:?}", integer.coords());
39
+ let logger = VerbosityFilter { max_verbosity: 3, inner: StderrLogger };
40
+ logger.log(5, "FYI");
41
+ logger.log(2, "Uhoh");
31
42
}
32
43
```
33
44
34
45
<details >
35
46
36
- - _ Q:_ Why ` T ` is specified twice in ` impl<T> Point<T> {} ` ? Isn't that
37
- redundant?
47
+ - _ Q:_ Why ` L ` is specified twice in ` impl<L: Logger> .. VerbosityFilter<L> ` ?
48
+ Isn't that redundant?
38
49
- This is because it is a generic implementation section for generic type.
39
50
They are independently generic.
40
- - It means these methods are defined for any ` T ` .
41
- - It is possible to write ` impl Point<u32> { .. } ` .
42
- - ` Point ` is still generic and you can use ` Point<f64> ` , but methods in this
43
- block will only be available for ` Point<u32> ` .
44
-
45
- - Try declaring a new variable ` let p = Point { x: 5, y: 10.0 }; ` . Update the
46
- code to allow points that have elements of different types, by using two type
47
- variables, e.g., ` T ` and ` U ` .
51
+ - It means these methods are defined for any ` L ` .
52
+ - It is possible to write ` impl VerbosityFilter<StderrLogger> { .. } ` .
53
+ - ` VerbosityFilter ` is still generic and you can use ` VerbosityFilter<f64> ` ,
54
+ but methods in this block will only be available for
55
+ ` Point<StderrLogger> ` .
48
56
49
57
</details >
0 commit comments