如何扩展另一个板条箱中定义的特征?

问题描述 投票:0回答:2

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

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
特征添加一个新方法,但找不到适用于此的示例

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

rust traits
2个回答
8
投票

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


编写一个新特征,
    IteratorExt
  1. ,其中包含您的自定义方法。
    为任何实现 
  2. impl
  3. 的类型编写一个实现
    IteratorExt
    的毯子
    Iterator
    导入 
  4. IteratorExt
  5. 以访问您的扩展功能。
    
    
  6. 例如,我们可以向迭代器添加一个名为
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 社区对于这是否是合法做法或是否是需要避免的黑客行为存在一定分歧,因此您的情况可能会有所不同。


4
投票
扩展特征模式

这个想法是,您创建一个特征,通常按照惯例命名为

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();

	
© www.soinside.com 2019 - 2024. All rights reserved.