如何在 Rust 中扩展其他地方定义的 trait?

5
我想创建一个新的迭代器方法,例如:
let test_data = vec![1,2,3,1,1,1,1];
let indexes_with_val_1 = test_data.iter().find_all(|element| element == 1).unwrap();

assert_eq!(indexes_with_val_1, vec!(0,3,4,5,6));

我想要给 std::iter::Iterator trait 添加一个新的方法,但是找不到可行的示例。

逻辑上没有问题,因为我有一个可以正常工作的自由函数,只是为了更好的人机交互体验,我希望能像代码示例中使用它。

2个回答

6
您可以使用一种名为扩展特质的设计模式。您无法扩展Iterator特质,但您可以编写一个新的特质。这是我们要做的事情。
  1. 编写一个新特质,IteratorExt,其中包含您的自定义方法。
  2. 编写一个泛型impl,为实现Iterator的任何类型实现IteratorExt
  3. 导入IteratorExt以访问您的扩展函数。
例如,我们可以像这样向迭代器添加一个名为my_extension的简单函数。
trait IteratorExt {

  fn my_extension(self) -> Self;

}

impl<T: Iterator> IteratorExt for T {

  fn my_extension(self) -> Self {
    println!("Hey, it worked!");
    self
  }

}

pub fn main() {
  let x = vec!(1, 2, 3, 4);
  let y = x.iter().my_extension().map(|x| x + 1).collect::<Vec<_>>();
  println!("{:?}", y);
}

唯一的缺点是你必须导入新特性才能使用它。因此,如果你想在另一个文件中使用my_extension,你必须明确导入IteratorExt才能这样做。
根据我的经验,Rust社区在是否采用这种做法方面存在分歧,有人认为这是合法的做法,而有人则认为这是应该避免的hack。所以,你的体验可能会有所不同。

解释得非常清楚,直到我读了你的回答,我才完全明白。谢谢你! - undefined

2

对于这个问题,存在扩展特质模式

其思想是创建一个特质,通常按照惯例命名为TraitExt,并为所有实现Trait的实现进行实现:

pub trait IteratorExt {
    fn my_iterator_extension(&self);
}

impl<I: Iterator + ?Sized> IteratorExt for I {
    fn my_iterator_extension(&self) {
        // Do work.
    }
}

my_iterator.my_iterator_extension();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接