问题描述
我有一个 Config
结构,可以存储一个 FnMut
回调函数。问题是:并非我的所有配置都需要回调函数,因此我想将添加回调函数设为可选。这需要使用默认函数初始化成员变量,如果没有设置回调,该函数将被使用。
现有代码
struct Config<'a>{
callback: &'a mut dyn (FnMut(&str))
}
fn default_fn(msg: &str){
println!("default_fn({})", msg);
}
impl<'a> Config<'a> {
pub fn new() -> Config<'a> {
Config{
callback: &default_fn // ERROR: types differ in mutability
}
}
pub fn set_callback(mut self, callback_fn: &'a mut dyn (FnMut(&str))) -> Config<'a> {
self.callback = callback_fn;
self
}
}
fn main() {
// Our FnMut callback
let mut msg_log: Vec<String> = vec![];
let mut callback_fn = |msg: &str| {
msg_log.push(msg.to_string());
};
{
let mut config = Config::new();
(config.callback)("Hello World!");
config = config.set_callback(&mut callback_fn);
(config.callback)("Hello World!");
}
// Demonstration that the callback actually works
println!("{:?}", msg_log);
}
error[E0308]: mismatched types
--> src/main.rs:13:23
|
13 | callback: &default_fn // ERROR: types differ in mutability
| ^^^^^^^^^^^ types differ in mutability
|
= note: expected type `&mut dyn for<'r> std::ops::FnMut(&'r str)`
found type `&for<'r> fn(&'r str) {default_fn}`
有人对如何解决这个问题有什么建议吗?
我已经尝试过,但没有成功:
- 使用闭包对其进行初始化:
回调:&|_: &str|{}
- 使用成员函数而不是全局函数
- 创建可变引用:
回调:&mut default_fn
(原因:无法返回引用临时值的值
)
我的想法已经用完了,感谢任何帮助。即使答案是由于我尚未意识到的原因,我正在尝试做的事情是不可能的。
最佳答案
你真的应该把 trait 对象函数装箱。这使得整个代码更易于使用:
struct Config<'a>{
callback: Box<dyn FnMut(&str) + 'a>,
}
fn default_fn(msg: &str){
println!("default_fn({})", msg);
}
impl<'a> Config<'a> {
pub fn new() -> Config<'a> {
Config{
callback: Box::new(default_fn)
}
}
pub fn set_callback(self, callback: &'a mut dyn (FnMut(&str))) -> Config<'a> {
Config {
callback: Box::new(callback),
..self
}
}
}
fn main() {
// Our FnMut callback
let mut msg_log = vec![];
let mut callback_fn = |msg: &str| {
msg_log.push(msg.to_string());
};
{
let mut config = Config::new();
(config.callback)("Hello World!");
config = config.set_callback(&mut callback_fn);
(config.callback)("Hello World!");
}
// Demonstration that the callback actually works
println!("{:?}", msg_log);
}
请注意,在惯用的 Rust 中很难使用回调。我什至会说它们根本不是惯用语。你应该使用 channel , 类似这样的东西:
use std::sync::mpsc::{channel, Sender, SendError};
struct Config {
sender: Sender<String>,
}
impl Config {
pub fn new(sender: Sender<String>) -> Config {
Config{
sender
}
}
pub fn send(&self, message: String) -> Result<(), SendError<String>> {
self.sender.send(message)
}
}
fn main() {
let (sender, receiver) = channel();
let config = Config::new(sender);
config.send("Hello world!".into()).unwrap();
println!("{:?}", receiver.recv().unwrap());
}
关于rust - 使用静态 Fn 函数初始化 FnMut 成员变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57905873/