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



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

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性状添加一个新方法但是找不到适合这个的例子

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

您可以使用一种称为扩展特性的设计模式。您不能扩展Iterator特性,但可以编写一个新的。这就是我们要做的。

  1. 写一个新的trait,IteratorExt,里面有你的自定义方法
  2. 为实现Iterator的任何类型编写一个实现IteratorExt的毯子impl
  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社区对这是合法的做法还是应该避免的黑客行为存在分歧,因此您的看法可能会有所不同。

存在扩展性状模式。

这个想法是你创建一个trait,通常按照约定命名为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();

最新更新