解决扩展特征的局限性

时间:2014-12-03 09:19:55

标签: iterator rust traits

Foo的所有实例实施对象安全特征FooExt和(可能不安全)扩展特征Foo的模式现在似乎已成为标准。

https://github.com/rust-lang/rfcs/pull/445

对于Iterator<A>,这是一个问题,因为我有一个库来覆盖旧迭代器特征的默认方法IteratorExt#last()(底层库有last()的有效实现1}})。现在这是不可能的,因为对于任何AIteratorExt始终存在冲突的特征实施,libcore已经为所有Iterator<A>提供的实施。

iterator.rs:301:1: 306:2 error: conflicting implementations for trait `core::iter::IteratorExt` [E0119]

iterator.rs:301 impl<'a, K: Key> iter::IteratorExt<Vec<u8>> for ValueIterator<'a,K,Vec<u8>> {
iterator.rs:302   fn last(&mut self) -> Option<Vec<u8>> {
iterator.rs:303      self.seek_last();
iterator.rs:304      Some(self.value())
iterator.rs:305   }
iterator.rs:306 }
...

现在,据我所知,我有两个选择:

  • 有我自己的特点和我自己的last()实现。如果导入IteratorExt除非经过仔细使用,这意味着它会发生冲突。如果使用来自last()的版本,这也有意外使用IteratorExt的低效版本的危险。我无法轻松访问IteratorExt
  • 拥有自己的特征并以不同的方式命名方法(seek_last())。缺点:我要求用户学习词汇,并始终支持我的方法而不是IteratorExt提供的方法。同样的问题:我想避免意外使用last()

我还缺少其他更好的解决方案吗?

2 个答案:

答案 0 :(得分:2)

rustc 0.13.0-nightly (8bca470c5 2014-12-08 00:12:30 +0000)开始定义last()作为您的类型的固有方法应该有效。

#[deriving(Copy)]
struct Foo<T> {t: T}

impl<T> Iterator<T> for Foo<T> {
    fn next(&mut self) -> Option<T> { None }
}

// this does not work
// error: conflicting implementations for trait `core::iter::IteratorExt` [E0119]
// impl<T> IteratorExt<T> for Foo<T> {
//    fn last(mut self) -> Option<T> { None }
//}

// but this currently does
impl<T> Foo<T> {
    fn last(mut self) -> Option<T> { Some(self.t) }
}


fn main() {
    let mut t = Foo{ t: 3u };
    println!("{}", t.next())
    println!("{}", t.last()) // last has been "shadowed" by our impl
    println!("{}", t.nth(3)) // other IteratorExt methods are still available
}

由于您不应该使用扩展特征作为通用边界(但只是为了提供其他方法),理论上这应该适用于您的场景,因为您可以拥有自己的类型及其impl箱。

您的类型的用户将使用固有的last方法而不是IteratorExt上的方法,但仍然可以使用IteratorExt上的其他方法。

答案 1 :(得分:0)

last应移至Iterator,而不是IteratorExt

使用IteratorExt个对象时需要

Box<Iterator>,以允许在其上调用泛型方法(例如map),因为您无法在vtable中放置泛型方法。但是,last不是通用的,因此可以放入Iterator