X-Git-Url: https://git.ralfj.de/rust-101.git/blobdiff_plain/39b387735112972cad7bb3175393a0a09d767335..0223210576f27d0743c2d12b890d30f5c2ef6b2d:/workspace/src/part11.rs?ds=sidebyside diff --git a/workspace/src/part11.rs b/workspace/src/part11.rs index f868a3c..cc2a252 100644 --- a/workspace/src/part11.rs +++ b/workspace/src/part11.rs @@ -1,9 +1,8 @@ -// Rust-101, Part 11: Trait Objects, Box (WIP) -// =========================================== - +// Rust-101, Part 11: Trait Objects, Box, Rc, Lifetime bounds +// ========================================================== mod callbacks { - // For now, we just decide that the callbakcs have an argument of type `i32`. + // For now, we just decide that the callbacks have an argument of type `i32`. struct CallbacksV1 { callbacks: Vec, } @@ -12,23 +11,23 @@ mod callbacks { callbacks: Vec, } */ - struct Callbacks { + pub struct Callbacks { callbacks: Vec>, } impl Callbacks { // Now we can provide some functions. The constructor should be straight-forward. - fn new() -> Self { + pub fn new() -> Self { unimplemented!() } // Registration simply stores the callback. - fn register(&mut self, callback: Box) { + pub fn register(&mut self, callback: Box) { unimplemented!() } // And here we call all the stored callbacks. - fn call(&mut self, val: i32) { + pub 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!() @@ -36,47 +35,48 @@ mod callbacks { } } - // Now we are read for the demo. - pub fn demo() { - let mut c = Callbacks::new(); + // Now we are ready for the demo. + pub fn demo(c: &mut Callbacks) { 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); + c.register(Box::new(move |val| { + count = count+1; + println!("Callback 2, {}. time: {}", count, val); + } )); + c.call(1); c.call(2); } - } // Remember to edit `main.rs` to run the demo. pub fn main() { - callbacks::demo(); + let mut c = callbacks::Callbacks::new(); + callbacks::demo(&mut c); } mod callbacks_clone { - use std::rc; + use std::rc::Rc; #[derive(Clone)] - struct Callbacks { - callbacks: Vec>, + pub struct Callbacks { + callbacks: Vec>, } - // The methods on these clonable callbacks are just like the ones above. impl Callbacks { - fn new() -> Self { + pub fn new() -> Self { unimplemented!() } - fn register(&mut self, callback: rc::Rc) { + // For the `register` function, we don't actually have to use trait objects in the argument. + + pub fn register(&mut self, callback: F) { 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. + pub fn call(&mut self, val: i32) { + // We only need a shared iterator here. `Rc` also implicitly dereferences, so we can simply call the callback. for callback in self.callbacks.iter() { unimplemented!() } @@ -84,12 +84,9 @@ mod callbacks_clone { } // 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))); - - c.call(0); - c.call(1); + fn demo(c: &mut Callbacks) { + c.register(|val| println!("Callback 1: {}", val)); + c.call(0); c.call(1); } } @@ -97,3 +94,4 @@ mod callbacks_clone { // 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. +