繁体   English   中英

为另一个特征实现和使用特征

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM