Merge branch 'master' of git://ralfj.de/rust-101
[rust-101.git] / workspace / src / part11.rs
1 // Rust-101, Part 11: Trait Objects, Box, Lifetime bounds
2 // ======================================================
3
4
5 // For now, we just decide that the callbacks have an argument of type `i32`.
6 struct CallbacksV1<F: FnMut(i32)> {
7     callbacks: Vec<F>,
8 }
9
10 /* struct CallbacksV2 {
11     callbacks: Vec<FnMut(i32)>,
12 } */
13
14 pub struct Callbacks {
15     callbacks: Vec<Box<FnMut(i32)>>,
16 }
17
18 impl Callbacks {
19     // Now we can provide some functions. The constructor should be straight-forward.
20     pub fn new() -> Self {
21         unimplemented!()
22     }
23
24     // Registration simply stores the callback.
25     pub fn register(&mut self, callback: Box<FnMut(i32)>) {
26         self.callbacks.push(callback);
27     }
28
29     // We can also write a generic version of `register`, such that it will be instantiated with some concrete closure type `F`
30     // and do the creation of the `Box` and the conversion from `F` to `FnMut(i32)` itself.
31     
32     pub fn register_generic<F: FnMut(i32)+'static>(&mut self, callback: F) {
33         unimplemented!()
34     }
35
36     // And here we call all the stored callbacks.
37     pub fn call(&mut self, val: i32) {
38         // Since they are of type `FnMut`, we need to mutably iterate.
39         for callback in self.callbacks.iter_mut() {
40             unimplemented!()
41         }
42     }
43 }
44
45 // Now we are ready for the demo. Remember to edit `main.rs` to run it.
46 pub fn main() {
47     let mut c = Callbacks::new();
48     c.register(Box::new(|val| println!("Callback 1: {}", val)));
49     c.call(0);
50
51     {
52         let mut count: usize = 0;
53         c.register_generic(move |val| {
54             count = count+1;
55             println!("Callback 2: {} ({}. time)", val, count);
56         } );
57     }
58     c.call(1); c.call(2);
59 }
60
61
62 // **Exercise 11.1**: We made the arbitrary choice of using `i32` for the arguments. Generalize the data structures above
63 // to work with an arbitrary type `T` that's passed to the callbacks. Since you need to call multiple callbacks with the
64 // same `t: T`, you will either have to restrict `T` to `Copy` types, or pass a reference.
65