我知道 * 通常 * 您不能使用Vec<dyn Iterator>>
之类的类型,因为您当然需要指定关联的类型。
现在,我当然可以有Vec<Box<dyn Iterator<Item=i32>>>
。
但是像这样的事情呢:
trait Foo {}
#[derive(Clone)]
struct Bla;
impl Foo for Bla {}
#[derive(Clone)]
struct Bar;
impl Foo for Bar {}
fn main () {
// this works of course
let x: Vec<Box<dyn Iterator<Item=i32>>> = vec![];
// this can be defined
let mut y: Vec<Box<dyn Iterator<Item=Box<dyn Foo>>>> = vec![];
// but how do I use it? these don't work
let first_it = Box::new(std::iter::repeat(Box::new(Bar{})));
let second_it = Box::new(std::iter::repeat(Box::new(Bla{})).take(10));
y.push(first_it);
y.push(second_it);
}
编译器抱怨:
expected `std::iter::Repeat<Box<Bar>>` to be an iterator that yields `Box<dyn Foo>`, but it yields `Box<Bar>`
显然,尽管Bar
实现了Foo
,但Box<Bar>
不被认为是Box<dyn Foo>
的可接受子类型。
我知道Rust没有其他语言所具有的超高阶关联类型,我所尝试做的是根本不可能的还是Rust不支持?
在我看来,使用y
不应该有一个 * 固有的 * 类型问题,它包含的所有元素都将是产生某些项的迭代器,所有这些项都将实现相同的trait,Foo
。
或者我只是在 * 创建 * trait对象时做错了什么?
1条答案
按热度按时间osh3o9ms1#
Iterator<Item=Box<Bar>>
和Iterator<Item=Box<dyn Foo>>
之间存在结构不兼容性。如果您不知道,Box<Bar>
的大小与Box<dyn Foo>
不同(内部单指针与两个指针)。您可以将
Box<Bar>
转换(或者更确切地说是强制转换)为Box<dyn Foo>
,因为Bar
实现了Foo
,但是您不能将Iterator<Item=Box<Bar>>
冒充为Iterator<Item=Box<dyn Foo>>
,因为需要有一个地方来进行转换。所以,是的,你可以拥有这样一个集合,但是你需要主动地使用正确的trait对象: