如何在不使用装箱与泛型的情况下将实现trait的结构体赋值给结构体字段?
解决方案:用枚举封装所有trait实现类型
在Rust中,dyn Namable属于动态大小类型(DST),结构体的字段必须是编译时大小确定的类型,所以不能直接把dyn Namable作为字段。除了泛型和装箱,你可以通过枚举来封装所有可能实现Namable的结构体,以此实现无需装箱的静态分发。
具体实现步骤如下:
- 定义一个枚举,包含所有需要的
trait实现类型 - 为这个枚举实现
Namabletrait - 在
UserCertification中使用这个枚举作为字段类型
修改后的完整代码:
#[derive(Copy, Clone)] enum Job { Teacher, Police } trait Namable { fn name(&self) -> &'static str; } // Sample trait-implemented struct 1 struct TemporaryTeacher { } impl Namable for TemporaryTeacher { fn name(&self) -> &'static str { "T.Teacher" } } // Sample trait-implemented struct 2 struct GeneralTeacher { } impl Namable for GeneralTeacher { fn name(&self) -> &'static str { "G.Teacher" } } // 用枚举封装所有实现Namable的类型 enum WorkRole { Temporary(TemporaryTeacher), General(GeneralTeacher), } // 为枚举实现Namable trait impl Namable for WorkRole { fn name(&self) -> &'static str { match self { WorkRole::Temporary(t) => t.name(), WorkRole::General(g) => g.name(), } } } // 修改create_named_object返回枚举类型 fn create_named_object(job: Job, name: &str) -> WorkRole { match job { Job::Teacher => WorkRole::Temporary(TemporaryTeacher()), Job::Police => todo!(), // 可以在这里扩展其他角色 } } struct UserCertification { name: String, current_work: WorkRole, // 使用枚举类型,无需装箱 } fn main() { let named_object = create_named_object(Job::Teacher, ""); let user = UserCertification { name: "John".to_string(), current_work: named_object, }; println!("{}", user.current_work.name()); // 输出:T.Teacher }
优缺点说明
- 优点:完全静态分发,没有装箱带来的堆内存分配和运行时开销;类型安全,编译时就能检查所有可能的类型。
- 缺点:需要提前枚举所有可能的
trait实现类型,如果后续要新增实现Namable的结构体,必须修改枚举定义,扩展性不如泛型或动态分发。
内容的提问来源于stack exchange,提问作者Gullakjistra
相关产品推荐
相关产品推荐

