Macro stakker::actor_of_trait
source · macro_rules! actor_of_trait { ($core:expr, $trait:ident, $type:ident :: $init:ident($($x:expr),* $(,)? ), $notify:expr) => { ... }; ($core:expr, $trait:ident, <$type:ty> :: $init:ident($($x:expr),* $(,)? ), $notify:expr) => { ... }; }
Expand description
Create a new actor that implements a trait and initialise it
ⓘ
let actor = actor_of_trait!(core, BoxedTrait, Type::init(args...), notify);
let actor = actor_of_trait!(core, BoxedTrait, <path::Type>::init(args...), notify);
This allows treating a set of actors that all implement a trait equally in the calling code. The actors have to be defined slightly differently to make this work. Here’s a short example:
// Trait definition
type Animal = Box<dyn AnimalTrait>;
trait AnimalTrait {
fn sound(&mut self, cx: CX![Animal]);
}
struct Cat;
impl Cat {
fn init(_: CX![Animal]) -> Option<Animal> {
Some(Box::new(Self))
}
}
impl AnimalTrait for Cat {
fn sound(&mut self, _: CX![Animal]) {
println!("Miaow");
}
}
struct Dog;
impl Dog {
fn init(_: CX![Animal]) -> Option<Animal> {
Some(Box::new(Self))
}
}
impl AnimalTrait for Dog {
fn sound(&mut self, _: CX![Animal]) {
println!("Woof");
}
}
let mut stakker = Stakker::new(Instant::now());
let s = &mut stakker;
// This variable can hold any kind of animal
let mut animal: ActorOwn<Animal>;
animal = actor_of_trait!(s, Animal, Cat::init(), ret_nop!());
call!([animal], sound());
animal = actor_of_trait!(s, Animal, Dog::init(), ret_nop!());
call!([animal], sound());
// To separate creation and initialisation, do it this way:
animal = actor_new!(s, Animal, ret_nop!());
call!([animal], Cat::init());
call!([animal], sound());
s.run(Instant::now(), false);
See also ActorOwnAnon
for an alterative approach to the same
problem.
Implemented using ActorOwn::new
.