给定一个具有“处理程序”成员的“委托(delegate)”结构,我如何使用动态字符串调用处理程序?
pub struct Processor {
callback: Box<FnMut()>,
message: Option<String>
}
impl Processor {
pub fn new<CB: 'static + FnMut()>(c: CB) -> Self {
Processor {
callback: Box::new(c),
message: Some("".into())
}
}
pub fn set_callback<CB: 'static + FnMut(&str)>(&mut self, callback: CB) {
self.callback = Box::new(callback);
}
pub fn set_message<S>(&mut self, message: S) where S: Into<String> {
self.message = Some(message.into());
}
pub fn process(&mut self) {
match self.message {
Some(string) => {
if self.message.chars().count() > 0 {
(self.callback)(self.message);
} else {
(self.callback)();
}
},
None => {}
}
}
}
impl EventEmitter {
pub fn new() -> Self {
EventEmitter {
delegates: Vec::new()
}
}
/// Register an Event and a handler
pub fn on(&mut self, event: Event, handler: Processor) {
self.delegates.push(Delegate::new(event, handler))
}
/// Run handlers on the emitted event
pub fn emit(&mut self, name: &'static str/*, with message!! */) {
for delegate in self.delegates.iter_mut(){
if delegate.event.name == name {
delegate.handler.process();
}
}
}
/// Run handlers on the emitted event
pub fn emit_with(&mut self, name: &'static str, message: &'static str) {
for delegate in self.delegates.iter_mut() {
if delegate.event.name == name {
delegate.handler.set_message(message);
delegate.handler.process();
}
}
}
}
然后我有:
emitter.on(
Event::new("TEST"),
Processor::new(|x| println!("Test: {}", x))
);
emitter.emit_with("TEST", "test");
但是编译器提示:
--> src/main.rs:97:3
|
97 | Processor::new(|x| println!("Test: {}", x))
| ^^^^^^^^^^^^^^ --- takes 1 argument
| |
| expected closure that takes 0 arguments
如果我删除 set_callback() 定义中的“&str”类型参数:
set_callback<CB: 'static + FnMut()>(&mut self, callback: CB)
我可以使用不接受任何参数的闭包来实现它:
emitter.on( // emitter.emit("TEST");
Event::new("TEST"),
Processor::new(|| println!("static string."))
);
有没有办法将字符串传递给最终可以传递给处理程序的 emit_with() 函数?
最佳答案
在这里你写了:
pub struct Processor {
callback: Box<FnMut(/* RIGHT HERE */)>,
message: Option<String>
}
您已经声明了一个 FnMut
(闭包)不带任何参数。
语法是 FnMut(/* arguments to closure */)
, 但你还没有提供任何。因此,您不能向它传递一个确实接受参数的闭包。
您不能拥有一个既接受参数又不接受参数的闭包。
此外,您使用了 FnMut(&str)
,但只在一个地方。你在任何地方都需要它。由于您想传递或不传递字符串,我已将其转换为 Optional<&str>
(所以闭包类型是 FnMut(Option<&str>)
)。
我修改了您的代码,使闭包采用可选的 &str
。 .
这就是我建议您处理此问题的方式:
pub struct Processor {
// The closure takes an optional string.
callback: Box<FnMut(Option<&str>)>,
message: Option<String>
}
impl Processor {
pub fn new<CB: 'static + FnMut(Option<&str>)>(c: CB) -> Self {
Processor {
callback: Box::new(c),
message: Some("".into())
}
}
pub fn set_callback<CB: 'static + FnMut(Option<&str>)>(&mut self, callback: CB) {
self.callback = Box::new(callback);
}
pub fn set_message<S>(&mut self, message: S) where S: Into<String> {
self.message = Some(message.into());
}
pub fn process(&mut self) {
match self.message {
Some(string) => {
// NOTE: Instead of .chars().count > 0
if !self.message.is_empty() {
(self.callback)(Some(self.message));
} else {
(self.callback)(None);
}
},
None => {}
}
}
}
注意:这是未经测试的,但应该可以工作。如果出现任何错误,请发表评论。
关于rust - 如何将参数传递给存储的回调?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54548563/