chris-morgan / mopa

MOPA: My Own Personal Any. A macro to implement all the `Any` methods on your own trait.
Other
112 stars 9 forks source link

A real-world example #9

Open sdroege opened 7 years ago

sdroege commented 7 years ago

In the documentation you're looking for a real-world example, and here I have one. Condensed it looks like this (and you guess right if you think this is actually related to FFI under the hood).

I have a struct

struct Foo {
  imp: Box<FooImp>,
}

and a trait

trait FooImp: mopa::Any {
    // things in here
}

The use case here is that Foo is a generic thing with exchangeable implementation, but I want it to be with dynamic dispatch and not generic for reasons (if needed I can explain).

Now all fine so far, but Foo is actually always passed around as an Arc<Foo>, and it's possible to connect "notifications" to Foo

impl Foo {
    fn connect_notification<F: Fn(&Foo)>(&self, func: F) {
        ...
    }
}

Now a FooImp implementation might want to connect to some notification. But it wants to get access to itself again somehow. Here we need mopa:

impl Foo {
    fn get_imp(&self) -> &FooImp { ... }
}
let self: &SomeFooImpl;
let foo: &Foo;

foo.connect_notification(|foo| {
    let ourself = foo.get_imp().downcast_ref::<SomeFooImpl>().unwrap();
    ...
});