如何在Rust中将结构体方法存入Vector?含可变方法需求及报错处理
解决Rust结构体方法存入Vector的问题
原代码错误分析
你遇到的编译错误核心原因有两点:
- Rust中不能通过
&self.get_fruit直接获取方法引用,方法不是结构体字段,必须通过类型名调用的方式获取函数指针 Vec<fn()>的类型签名和get_fruit不匹配——get_fruit需要接收&FruitStore作为参数,对应的函数指针类型应为fn(&FruitStore)
下面分场景给出解决方案,同时覆盖可变方法的处理:
场景1:存储未绑定实例的方法(函数指针)
这种方式存储的是不绑定具体实例的函数,调用时需要传入结构体实例的引用,适合需要复用方法到多个实例的场景。
fn main() {} struct FruitStore { fruit: String, } impl FruitStore { pub fn calculate(&self) { // 定义对应方法签名的函数指针类型 let mut x: Vec<fn(&FruitStore)> = vec![]; // 通过类型名::方法名获取未绑定的函数指针 x.push(FruitStore::get_fruit); // 调用示例:传入实例引用执行方法 for method in x { method(self); } } pub fn get_fruit(&self) { println!("当前水果:{}", self.fruit); } }
场景2:存储绑定实例的方法(闭包)
如果希望存储的方法无需额外传参,直接调用,可通过闭包捕获当前实例的引用,此时需要用Box<dyn Fn()>存储闭包(闭包是匿名类型,需用 trait object 包装)。
fn main() { let store = FruitStore { fruit: "苹果".to_string() }; store.calculate(); } struct FruitStore { fruit: String, } impl FruitStore { pub fn calculate(&self) { let mut x: Vec<Box<dyn Fn()>> = vec![]; // 闭包捕获self的引用,包装为Box存入Vector x.push(Box::new(|| self.get_fruit())); // 直接调用闭包 for func in x { func(); } } pub fn get_fruit(&self) { println!("当前水果:{}", self.fruit); } }
场景3:处理可变方法
未绑定的可变方法函数指针
可变方法对应的函数指针类型为fn(&mut FruitStore),调用时需传入实例的可变引用:
fn main() { let mut store = FruitStore { fruit: "苹果".to_string() }; store.calculate_mut(); } struct FruitStore { fruit: String, } impl FruitStore { pub fn calculate_mut(&mut self) { let mut x: Vec<fn(&mut FruitStore)> = vec![]; x.push(FruitStore::update_fruit); // 传入可变引用执行方法 for method in x { method(self); } } pub fn update_fruit(&mut self) { self.fruit = "香蕉".to_string(); println!("更新后水果:{}", self.fruit); } }
绑定实例的可变闭包
可变闭包需要实现FnMut trait,因此Vector类型应为Vec<Box<dyn FnMut()>>:
fn main() { let mut store = FruitStore { fruit: "苹果".to_string() }; store.calculate_mut(); } struct FruitStore { fruit: String, } impl FruitStore { pub fn calculate_mut(&mut self) { let mut x: Vec<Box<dyn FnMut()>> = vec![]; // 捕获可变引用self,闭包类型为FnMut() x.push(Box::new(|| self.update_fruit())); // 调用时需要mut修饰闭包,因为FnMut需要可变访问权限 for mut func in x { func(); } } pub fn update_fruit(&mut self) { self.fruit = "香蕉".to_string(); println!("更新后水果:{}", self.fruit); } }
内容的提问来源于stack exchange,提问作者ender maz
相关产品推荐
相关产品推荐

