我有一个想要用作迭代器的特性,并且我希望迭代器实现能够使用自定义特性实现。在 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())
}
}
最佳答案
理想情况下,您将为实现Iterator
的任何内容编写毯子式Generator
实现,例如:
impl<T: Generator> Iterator for T {
// ...
}
但是Rust不会接受这一点,因为您无法提供您自己的 crate 中未定义的特征的全面实现-这会违反orphan rule。但是,没有什么可以阻止您将任何
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()
}
playground中的可运行代码。
关于rust - 实现并使用另一个特征的特征,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65065190/