已添加Sized约束,为何编译器仍报错无法将Player trait转为动态对象?
解决Rust中
trait Player cannot be made into an object编译错误 错误原因
你给Player trait添加Sized约束的操作正好是问题的根源:dyn Trait属于动态大小类型(DST),它本身不满足Sized约束。而你的trait要求所有实现者必须是Sized,这就直接排除了将trait Player用作动态对象的可能,编译器因此报错。
解决方案
步骤1:修正Player trait定义
移除trait上的Sized约束,确保trait具备对象安全性:
trait Player: Fn(&BoardState) -> u8 {}
步骤2:自动为符合条件的类型实现trait Player
为所有满足Fn(&BoardState) -> u8的类型(包括普通函数、闭包)自动实现Player trait,无需手动为每个玩家类型写实现:
impl<F: Fn(&BoardState) -> u8> Player for F {}
步骤3:使用智能指针存储动态对象
由于dyn Player是动态大小类型,无法直接放入数组,需要用Box<dyn Player>(拥有所有权的智能指针)来包装:
struct Game { players: [Box<dyn Player>; 2], // 其他游戏状态字段 }
示例:创建游戏实例
可以直接将普通函数或闭包包装进Box后存入数组:
// 示例:人类玩家函数 fn human_player(state: &BoardState) -> u8 { // 此处编写玩家决策逻辑 0 } // 示例:AI玩家闭包 let ai_player = |state: &BoardState| -> u8 { // 此处编写AI决策逻辑 1 }; // 初始化游戏 let game = Game { players: [Box::new(human_player), Box::new(ai_player)], };
简化方案:直接使用标准库trait
如果不需要自定义trait的额外功能,完全可以跳过Player trait,直接使用Box<dyn Fn(&BoardState) -> u8>,代码更简洁:
struct Game { players: [Box<dyn Fn(&BoardState) -> u8>; 2], } // 初始化方式和之前一致 let game = Game { players: [Box::new(human_player), Box::new(ai_player)], };
内容的提问来源于stack exchange,提问作者Tivadar Bánfalvi-Kovács
相关产品推荐
相关产品推荐

