[英]Implement and consume trait for another trait
我有一个特征,我希望能够将其用作迭代器,并且我希望迭代器实现利用自定义特征实现。 在 rust 中是否可能出现以下情况,其中两个特征实现相互依赖,还是推荐使用不同的架构?
trait Generator {
fn generate(&self) -> String;
fn generate_many(&self, count: usize) -> Vec<String> {
self.take(count).collect()
}
}
impl Iterator for dyn Generator {
type Item = String;
fn next(&mut self) -> Option<Self::Item> {
Some(self.generate())
}
}
编辑:
尝试超特质
trait Generator: Iterator {
type Item = String;
fn generate(&self) -> String;
fn generate_many(&self, count: usize) -> Vec<String> {
self.take(count).collect()
}
fn next(&mut self) -> Option<Self::Item> {
Some(self.generate())
}
}
理想情况下,您应该为实现Generator
的任何东西编写Iterator
的全面实现,例如:
impl<T: Generator> Iterator for T {
// ...
}
但是 Rust 不会接受,因为你不能提供你没有在你自己的 crate 中定义的特征的全面实现——这会违反孤儿规则。
但是,没有什么能阻止您将任何Generator
包装在您自己的实现Iterator
的泛型类型中:
struct Wrapped<G: Generator>(G);
impl<G: Generator> Iterator for Wrapped<G> {
// ...
}
这并不违反孤儿规则,因为一揽子实现仅适用于我们在本地定义的Wrapped
类型的变体,并且T
本身保持不变。 它是零开销,因为Wrapped<G>
只是直接存储G
,无论G
是什么,不引入分配或间接。
最后,您甚至不需要实现上述结构,您可以将包装留给标准库提供的iter::from_fn()
助手:
fn iter<G>(g: &G) -> impl Iterator<Item = String> + '_
where
G: Generator + ?Sized,
{
std::iter::from_fn(move || Some(g.generate()))
}
然后你可以使用iter()
来实现generate_many()
:
fn generate_many(&self, count: usize) -> Vec<String> {
iter(self).take(count).collect()
}
操场上的可运行代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.