在Rust中,存储闭包通常使用泛型和特征对象。由于闭包可以捕获环境,它们被视为具有不同类型的匿名函数。在Rust中,所有的闭包都实现了Fn
、FnMut
或FnOnce
中的一个。
使用泛型存储闭包
使用泛型是一种方法,这允许结构体存储任何类型的闭包,只要闭包实现了指定的trait。这种方法的优点是它避免了动态分配和间接调用的开销,但它要求闭包的类型在编译时已知,并且结构体本身也变成了泛型。
示例代码:
ruststruct MyStruct<T> where T: Fn(i32) -> i32, { closure: T, } impl<T> MyStruct<T> where T: Fn(i32) -> i32, { fn new(closure: T) -> Self { MyStruct { closure } } fn call(&self, arg: i32) -> i32 { (self.closure)(arg) } } fn main() { let add_one = |x: i32| x + 1; let my_struct = MyStruct::new(add_one); println!("Result: {}", my_struct.call(5)); // 输出: Result: 6 }
使用Box<dyn Fn()>
存储闭包
如果你需要在结构体中存储可以在运行时改变的闭包,或者不希望结构体因闭包而变成泛型,可以使用特征对象。这通常涉及将闭包放入一个Box
,从而在堆上进行动态分配。使用Box<dyn Fn()>
等方式能够让你在运行时存储并调用不同的闭包。
示例代码:
ruststruct MyStruct { closure: Box<dyn Fn(i32) -> i32>, } impl MyStruct { fn new<F>(closure: F) -> Self where F: 'static + Fn(i32) -> i32, { MyStruct { closure: Box::new(closure) } } fn call(&self, arg: i32) -> i32 { (self.closure)(arg) } } fn main() { let multiply_by_two = |x: i32| x * 2; let my_struct = MyStruct::new(multiply_by_two); println!("Result: {}", my_struct.call(5)); // 输出: Result: 10 }
选择正确的方法
- 泛型方法:适用于你知道将使用哪种类型的闭包,并且希望避免任何运行时性能开销。
- 特征对象方法:适用于当你需要在运行时更换不同的闭包或者不想让结构体因为闭包类型而变成泛型。
每种方法都有其适用场景,你可以根据具体需求选择最合适的方式。
2024年8月7日 17:15 回复