reference - 如何将具体类型的迭代器特征对象转换为特征对象的迭代器特征对象?

标签 reference rust iterator traits

我有一个特征,其中包含一个函数,用于返回对另一个特征的引用的迭代器,例如:

pub trait ParentInterface {
    fn children<'a>(&'a self) -> Box<dyn Iterator<Item = &'a ChildInterface>>;
}

pub trait ChildInterface {
    fn some_method(&self) -> bool;
}

当为存储具体值向量的具体类型实现此特征时,如何返回正确类型的迭代器?

pub struct ConcreteParent {
    my_children: Vec<ConcreteChild>,
}

pub struct ConcreteChild {
    my_value: bool,
}

impl ParentInterface for ConcreteParent {
    fn children<'a>(&'a self) -> Box<dyn Iterator<Item = &'a ChildInterface>> {
        Box::new(self.my_children.iter()) // Compiler error!
    }
}

impl ChildInterface for ConcreteChild {
    fn some_method(&self) -> bool {
        self.my_value
    }
}

上面的示例会产生 Rust 2018 的编译器错误:

error[E0271]: type mismatch resolving `<std::slice::Iter<'_, ConcreteChild> as std::iter::Iterator>::Item == &dyn ChildInterface`
  --> src/lib.rs:19:9
   |
19 |         Box::new(self.my_children.iter()) // Compiler error!
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `ConcreteChild`, found trait ChildInterface
   |
   = note: expected type `&ConcreteChild`
              found type `&dyn ChildInterface`
   = note: required for the cast to the object type `dyn std::iter::Iterator<Item = &dyn ChildInterface>`

我假设 my_children.iter() 返回一个具有错误 Item 类型(具体类型而不是特征类型)的迭代器 - 如何解决这个问题?

最佳答案

默认情况下,特征对象以'static为边界。您必须指定生命周期 'a 然后才能正确映射迭代器 ( source ):

pub trait ParentInterface {
    fn children<'a>(&'a self) -> Box<dyn Iterator<Item = &'a dyn ChildInterface> + 'a>;
}

pub trait ChildInterface {
    fn some_method(&self) -> bool;
}

pub struct ConcreteParent {
    my_children: Vec<ConcreteChild>,
}

pub struct ConcreteChild {
    my_value: bool,
}

impl ParentInterface for ConcreteParent {
    fn children<'a>(&'a self) -> Box<dyn Iterator<Item = &'a dyn ChildInterface> + 'a> {
        Box::new(self.my_children.iter().map(|c| c as &'a dyn ChildInterface))
    }
}

impl ChildInterface for ConcreteChild {
    fn some_method(&self) -> bool {
        self.my_value
    }
}

注意更改:

  • 迭代器的引用边界是'a,就像项目一样:

    dyn Iterator</*...*/> + 'a
    
  • 每个具体类型都映射到一个特征对象:

    .map(|c| c as &'a dyn ChildInterface)
    

    请注意,您可以简化符号以使推理正常进行:.map(|c| c as _)

您可以使用生命周期'_进一步简化:

pub trait ParentInterface {
    fn children(&self) -> Box<dyn Iterator<Item = &dyn ChildInterface> + '_>;
}

// ...

impl ParentInterface for ConcreteParent {
    fn children(&self) -> Box<dyn Iterator<Item = &dyn ChildInterface> + '_> {
        Box::new(self.my_children.iter().map(|c| c as _))
    }
}

关于reference - 如何将具体类型的迭代器特征对象转换为特征对象的迭代器特征对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56496044/

相关文章:

c++ - 警告 : returning reference to temporary - strange case (Clarification for Rvalue)

java - String 在 Java 中如何成为引用类型?

c++ - 如何从(通常)返回引用(对成员数据)的成员函数返回常量

c# - .NET 项目中的条件引用是否可以消除警告?

rust - 如何为 Rust : cargo run? 创建快捷键

rust - 如何将可变长度数组添加到 Vec 中?

java - 链表的自定义迭代器

iterator - 为什么 `FromIterator` 的实现使用 `IntoIterator` 而不是 `Iterator` ?

python - 单线检查迭代器是否产生至少一个元素?

java - 链表迭代器删除