Rust中能否创建关联类型实现共享trait的trait对象集合?
如何在Rust中创建返回 trait 对象的迭代器集合
你的问题核心在于Rust对关联类型和 trait 对象的协变限制:虽然Bar和Bla都实现了Foo,但Repeat<Box<Bar>>的Item是具体类型Box<Bar>,而你需要的迭代器Item是Box<dyn Foo>——Rust不会自动将返回具体类型的迭代器,转换为返回 trait 对象的迭代器,因为Iterator的Item是固定的关联类型,不存在隐式的协变转换。
这个需求完全可以实现,只需要显式将迭代器的元素类型转换为Box<dyn Foo>,有两种常见方式:
方式一:用map转换元素类型
在迭代器链中加入map,把每个具体的Box<Bar>/Box<Bla>强制转换为Box<dyn Foo>:
trait Foo {} struct Bla; impl Foo for Bla {} struct Bar; impl Foo for Bar {} fn main() { let mut y: Vec<Box<dyn Iterator<Item = Box<dyn Foo>>>> = Vec::new(); // 转换Repeat<Box<Bar>>的元素类型 y.push(Box::new( std::iter::Repeat::new(Box::new(Bar)) .map(|b| b as Box<dyn Foo>) )); // 转换take后的迭代器元素类型 y.push(Box::new( std::iter::Repeat::new(Box::new(Bla)) .take(10) .map(|b| b as Box<dyn Foo>) )); }
方式二:直接初始化返回 trait 对象的迭代器
在创建Repeat时,就把初始值转换为Box<dyn Foo>,这样整个迭代器的Item类型就是Box<dyn Foo>,后续的适配器(比如take)也会保留这个类型:
trait Foo {} struct Bla; impl Foo for Bla {} struct Bar; impl Foo for Bar {} fn main() { let mut y: Vec<Box<dyn Iterator<Item = Box<dyn Foo>>>> = Vec::new(); // 直接创建Repeat<Box<dyn Foo>> let repeat_bar: std::iter::Repeat<Box<dyn Foo>> = std::iter::Repeat::new(Box::new(Bar) as Box<dyn Foo>); y.push(Box::new(repeat_bar)); // 同理处理take后的迭代器 let repeat_bla = std::iter::Repeat::new(Box::new(Bla) as Box<dyn Foo>) .take(10); y.push(Box::new(repeat_bla)); }
为什么之前的写法会报错?
Rust中,每个具体的迭代器类型(比如Repeat<Box<Bar>>)的Item是编译期固定的关联类型,不能隐式地将Iterator<Item=T>向上转换为Iterator<Item=U>,哪怕T可以转换为U。必须显式调整迭代器的Item类型,使其匹配你需要的 trait 对象类型,才能被放入对应的集合中。
内容的提问来源于stack exchange,提问作者cadolphs
相关产品推荐
相关产品推荐

