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

nec*_*ine 7 rust

我想创建一个新的迭代器方法,例如:

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));
Run Code Online (Sandbox Code Playgroud)

所以本质上我想为该std::iter::Iterator特征添加一个新方法,但找不到适用于此的示例

逻辑不是问题,因为我有一个运行良好的免费函数,我只是希望能够像代码示例中那样使用它,以获得更好的人体工程学效果。

Sil*_*olo 7

您可以使用称为扩展特征的设计模式。您无法扩展该Iterator特征,但可以编写一个新特征。这就是我们要做的。

  1. 编写一个新特征 ,IteratorExt其中包含您的自定义方法。
  2. 编写一个毯子impl来实现IteratorExt任何实现Iterator.
  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);
}
Run Code Online (Sandbox Code Playgroud)

唯一的缺点是您必须导入新特征才能使用它。因此,如果您想my_extension在另一个文件中使用,则必须IteratorExt专门导入才能执行此操作。

根据我的经验,Rust 社区对于这是否是合法做法或是否是需要避免的黑客行为存在一定分歧,因此您的情况可能会有所不同。


Cha*_*man 3

为此存在扩展特征模式。

这个想法是,您创建一个特征,通常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();
Run Code Online (Sandbox Code Playgroud)