I want to create a registry of objects that all implement some trait. So the Registry struct has a register function. But if I declare it returning void type, I can only register one object, then borrow issue for the second one. I found a work around: the register function returns self as mutable, then I an reuse the registry returned and the compiler is OK. I found this a bit ridiculous. What is the proper way to maintain a registry of objects ? Here is the code that works
trait Doable {
fn do_it(&mut self);
}
struct Registry<'a> {
components: Vec<Box<&'a (dyn Doable)>>,
}
impl<'a> Registry<'a> {
fn register(&'a mut self, d: &'a impl Doable) -> &mut Registry<'a> {
self.components.push(Box::new(d));
self
}
}
struct Foo {
name: String,
value: u32,
}
impl Foo {
fn set_value(&mut self, v: u32) {
self.value = v
}
}
impl Doable for Foo {
fn do_it(&mut self) {
println!("The value of {} is {}", self.name, self.value);
}
}
struct Bar {
nm: String,
id: u32,
}
impl Bar {
fn set_id(&mut self, v: u32) {
self.id = v
}
}
impl Doable for Bar {
fn do_it(&mut self) {
println!("The id of {} is {}", self.nm, self.id);
}
}
fn main() {
let mut r = Registry {
components: Vec::new(),
};
let mut foo: Foo = Foo {
name: "foo".to_string(),
value: 0,
};
let mut bar: Bar = Bar {
nm: "bar".to_string(),
id: 0,
};
let mut baz: Foo = Foo {
name: "baz".to_string(),
value: 0,
};
let r1 = r.register(&foo);
let r2 = r1.register(&bar);
r2.register(&baz);
foo.set_value(41);
bar.set_id(5);
baz.set_value(11);
foo.do_it();
bar.do_it();
baz.do_it();
}
it works but I would like to have a better way for registering objects and then call them back using the trait...
The solution is to not sprinkle around lifetimes everywhere, only where needed, with
you tell the compiler that the mutable borrow lasts as long as any reference in
Registrywhich is plain wrong. If you remove the'afromselfit works: