这究竟是如何工作的取决于图书馆的具体情况。但一般的模式是,用一个状态调用的方法来实现一个特性,然后在参数实现其他特性时,为每个最多有X个参数的函数实现它(使用宏),这意味着能够从状态中提取参数。
例如:
pub struct State {
// ...
}
pub trait Extractor: Sized {
fn extract(state: &mut State) -> Self;
}
pub trait Handler<Args> {
fn call(&mut self, state: &mut State);
}
// The below is usually done with a macro.
impl<F: FnMut()> Handler<()> for F {
fn call(&mut self, _state: &mut State) {
self()
}
}
impl<Arg1: Extractor, F: FnMut(Arg1)> Handler<(Arg1,)> for F {
fn call(&mut self, state: &mut State) {
self(Arg1::extract(state))
}
}
impl<Arg1: Extractor, Arg2: Extractor, F: FnMut(Arg1, Arg2)> Handler<(Arg1, Arg2)> for F {
fn call(&mut self, state: &mut State) {
self(Arg1::extract(state), Arg2::extract(state))
}
}
pub fn call_handler<Args, H: Handler<Args>>(handler: &mut H, state: &mut State) {
handler.call(state);
}
键入擦除处理程序(例如,为了将所有处理程序存储在一起)可以按如下方式完成:
pub fn handler_to_dyn<Args, H: Handler<Args> + 'static>(
mut handler: H,
) -> Box<dyn FnMut(&mut State)> {
Box::new(move |state| handler.call(state))
}
尽管这通常伴随着额外的特征。