我有一个特征,该特征包含一个函数,该函数返回对另一个特征的引用的迭代器,例如:
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
类型(具体类型而不是特征类型)的迭代器-如何解决?
答案 0 :(得分:2)
默认情况下,特征对象以'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 _))
}
}