X-Git-Url: https://git.ralfj.de/rust-101.git/blobdiff_plain/39b387735112972cad7bb3175393a0a09d767335..7fdd4203f19f2fa9096d0a662acf22d447e57af1:/workspace/src/part11.rs diff --git a/workspace/src/part11.rs b/workspace/src/part11.rs index f868a3c..746aed9 100644 --- a/workspace/src/part11.rs +++ b/workspace/src/part11.rs @@ -1,98 +1,64 @@ -// Rust-101, Part 11: Trait Objects, Box (WIP) -// =========================================== +// Rust-101, Part 11: Trait Objects, Box, Lifetime bounds +// ====================================================== -mod callbacks { - // For now, we just decide that the callbakcs have an argument of type `i32`. - struct CallbacksV1 { - callbacks: Vec, - } - - /* struct CallbacksV2 { - callbacks: Vec, - } */ - - struct Callbacks { - callbacks: Vec>, - } +// For now, we just decide that the callbacks have an argument of type `i32`. +struct CallbacksV1 { + callbacks: Vec, +} - impl Callbacks { - // Now we can provide some functions. The constructor should be straight-forward. - fn new() -> Self { - unimplemented!() - } +/* struct CallbacksV2 { + callbacks: Vec, +} */ - // Registration simply stores the callback. - fn register(&mut self, callback: Box) { - unimplemented!() - } +pub struct Callbacks { + callbacks: Vec>, +} - // And here we call all the stored callbacks. - fn call(&mut self, val: i32) { - // Since they are of type `FnMut`, we need to mutably iterate. Notice that boxes dereference implicitly. - for callback in self.callbacks.iter_mut() { - unimplemented!() - } - } +impl Callbacks { + // Now we can provide some functions. The constructor should be straight-forward. + pub fn new() -> Self { + unimplemented!() } - // Now we are read for the demo. - pub fn demo() { - let mut c = Callbacks::new(); - c.register(Box::new(|val| println!("Callback 1: {}", val))); - - c.call(0); - - let mut count: usize = 0; - c.register(Box::new(move |val| { count = count+1; println!("Callback 2, {}. time: {}", count, val); } )); - c.call(1); - c.call(2); + // Registration simply stores the callback. + pub fn register(&mut self, callback: Box) { + self.callbacks.push(callback); } -} - -// Remember to edit `main.rs` to run the demo. -pub fn main() { - callbacks::demo(); -} - -mod callbacks_clone { - - use std::rc; - - #[derive(Clone)] - struct Callbacks { - callbacks: Vec>, + // We can also write a generic version of `register`, such that it will be instantiated with some concrete closure type `F` + // and do the creation of the `Box` and the conversion from `F` to `FnMut(i32)` itself. + + pub fn register_generic(&mut self, callback: F) { + unimplemented!() } - // The methods on these clonable callbacks are just like the ones above. - impl Callbacks { - fn new() -> Self { + // And here we call all the stored callbacks. + pub fn call(&mut self, val: i32) { + // Since they are of type `FnMut`, we need to mutably iterate. + for callback in self.callbacks.iter_mut() { unimplemented!() } - - fn register(&mut self, callback: rc::Rc) { - unimplemented!() - } - - fn call(&mut self, val: i32) { - // We only need a shared iterator here. `Rc` also implicitly dereferences, so we can just call the callback. - for callback in self.callbacks.iter() { - unimplemented!() - } - } } +} - // The demo works just as above. Our counting callback doesn't work anymore though, because we are using `Fn` now. - fn demo() { - let mut c = Callbacks::new(); - c.register(rc::Rc::new(|val| println!("Callback 1: {}", val))); +// Now we are ready for the demo. Remember to edit `main.rs` to run it. +pub fn main() { + let mut c = Callbacks::new(); + c.register(Box::new(|val| println!("Callback 1: {}", val))); + c.call(0); - c.call(0); - c.call(1); + { + let mut count: usize = 0; + c.register_generic(move |val| { + count = count+1; + println!("Callback 2: {} ({}. time)", val, count); + } ); } + c.call(1); c.call(2); } + // **Exercise 11.1**: We made the arbitrary choice of using `i32` for the arguments. Generalize the data-structures above // to work with an arbitrary type `T` that's passed to the callbacks. Since you need to call multiple callbacks with the // same `t: T`, you will either have to restrict `T` to `Copy` types, or pass a borrow.