Rust中如何将dyn trait向下转换为另一个trait对象?
根因说明
你为dyn B类型实现了A trait,但Rust不会自动在Box<dyn B>和Box<dyn A>之间做隐式转换,二者是完全独立的胖指针类型,各自携带不同的vtable信息。你用as转换失败大概率是生命周期匹配问题:默认impl A for dyn B仅匹配生命周期为'static的dyn B实例,如果你的dyn B带非'static生命周期,就找不到对应的A实现。
解决方案
方案1:保留通用A实现,调整生命周期适配
如果你希望所有B的trait对象统一复用你写的A实现,不需要每个实现B的类型单独写A的逻辑,可以调整impl的生命周期覆盖全场景:
// 原有impl仅适配'static生命周期的dyn B,修改为适配任意生命周期 impl<'a> A for dyn B + 'a { fn something(&self) { println!("hello from B") } } // 此时可以直接用as完成转换 fn downcast(b: Box<dyn B>) -> Box<dyn A> { b as Box<dyn A> }
如果你能保证所有使用的dyn B都是'static生命周期,那不需要修改原有impl,直接用上述转换代码即可。
方案2:子trait约束(适配业务允许的场景)
如果你要求所有实现B的类型都必须实现A,可以直接把B声明为A的子trait,转换零开销:
trait A { fn something(&self); } // 加超类约束,所有实现B的类型必须先实现A trait B: A {} // 不需要单独给dyn B写A的impl,转换直接成立 fn downcast(b: Box<dyn B>) -> Box<dyn A> { b }
内容的提问来源于stack exchange,提问作者mwlon
相关产品推荐
相关产品推荐

