I am quite new to Rust, coming from a Java background. I am trying to implement the observer pattern in Rust (I guess this is not idiomatic Rust, though). My attempt is like this:
use crate::observable::{Listener, trigger_listeners};
mod observable {
pub trait Listener {
fn trigger(&mut self);
}
pub fn trigger_listeners(listeners: Vec<&mut Box<dyn Listener>>) {
for mut x in listeners {
x.trigger();
}
}
}
struct Mock {
times_called: u32
}
impl Listener for Mock {
fn trigger(&mut self) {
self.times_called += 1;
}
}
#[test]
fn test() {
let mut mock = Box::new(Mock{ times_called: 0 });
trigger_listeners(vec![&mut mock]);
assert_eq!(mock.times_called, 1)
}
Every listener should implement the Listener trait and be passed as an array to the function trigger_listener.
This gives me the following error:
error[E0308]: mismatched types
--> src/lib.rs:27:28
|
27 | trigger_listeners(vec![&mut mock]);
| ^^^^^^^^^ expected trait observable::Listener, found struct `Mock`
|
= note: expected type `&mut std::boxed::Box<(dyn observable::Listener + 'static)>`
found type `&mut std::boxed::Box<Mock>`
error: aborting due to previous error
I was thinking that because the Mock implements the trait Listener, I can pass it as a reference.
My other try is to only use a Box which is moved (pub fn trigger_listeners(listeners: Vec<Box<dyn Listener>>) {}). This works, but then I cannot access the mock.times_called anymore.
I've also made some attempts with a Rc, but this didn't work either.