Rust中如何传递静态函数作为参数实现策略模式
Rust 策略模式实现方案
你当前的写法无法编译,核心问题有两个:
dyn Sorter是动态大小类型,不能直接作为函数参数传递,必须通过引用(&dyn Sorter)或智能指针(Box<dyn Sorter>)包裹- 你定义的
sort是trait的关联函数(无self参数),无法通过trait对象动态分发调用,也不能直接用实例点调用的方式访问
两种实现路径
你不需要强制给排序结构体加字段创建有状态实例,根据是否需要动态存储策略,可以选两种写法:
1. 静态分发(无运行时开销,适合固定策略场景)
保留你当前的关联函数写法,通过泛型约束指定排序策略类型,不需要创建任何结构体实例:
// 泛型参数S要求实现Sorter trait fn sort<S: Sorter, T: Ord + Copy>(arr: &mut Vec<T>, desc: bool) { S::sort(arr, desc); } // 调用示例 fn main() { let mut num_arr = vec![3, 7, 2, 9, 1]; // 显式指定使用冒泡排序 sort::<BubleSort, _>(&mut num_arr, false); }
这种写法编译期就会确定调用的排序逻辑,没有任何动态分发开销,但是不能把不同的排序策略存入同一个Vec做统一迭代。
2. 动态分发(支持存入Vec迭代调用)
如果需要在运行时动态切换策略、或者把多个策略存入集合,只需要给trait方法加&self参数即可。你的排序结构体都是无字段的单元结构体,创建实例不会产生任何额外内存开销:
// 调整trait方法签名,加&self参数 pub trait Sorter { fn sort<T: Ord + Copy>(&self, arr: &mut Vec<T>, desc: bool); } // 对应实现只需要同步加&self,内部逻辑不需要改动 impl Sorter for BubleSort { fn sort<T: Ord + Copy>(&self, arr: &mut Vec<T>, desc: bool) { // 原有冒泡排序逻辑 } } impl Sorter for SelectionSort { fn sort<T: Ord + Copy>(&self, arr: &mut Vec<T>, desc: bool) { // 原有选择排序逻辑 } }
调整后既可以传参调用,也可以把不同策略存入Vec统一迭代:
// 动态分发版本的调用函数 fn sort<T: Ord + Copy>(sorter: &dyn Sorter, arr: &mut Vec<T>, desc: bool) { sorter.sort(arr, desc); } fn main() { let mut arr = vec![4,2,5,1,3]; // 传入单元结构体实例调用,无构造开销 sort(&SelectionSort, &mut arr, false); // 把不同排序策略存入同一个Vec let sorter_list: Vec<Box<dyn Sorter>> = vec![ Box::new(BubleSort), Box::new(SelectionSort) ]; // 迭代调用所有排序策略 for (idx, sorter) in sorter_list.iter().enumerate() { let mut test_arr = vec![5,2,7,1,3,6]; sorter.sort(&mut test_arr, true); println!("排序器{}执行结果:{:?}", idx, test_arr); } }
提示:上述写法满足Rust的trait对象安全要求,泛型方法定义在trait的关联方法上而非trait本身,不会影响动态分发的正常运行。
内容的提问来源于stack exchange,提问作者Валентин Стайков
相关产品推荐
相关产品推荐

