2017-02-06 73 views
4

我有一個特質,我想說如果一個結構實現這個特性,那麼它也可以作爲Iterator。不過,當我嘗試使用一個結構體作爲迭代器時,我收到了一個編譯器錯誤。特質實現迭代器,但不能使用一個結構實現我的特徵作爲迭代器

我正在寫一個庫來從許多不同的文件格式讀取相同類型的數據。我想創建一個通用的「讀者」特徵,它將返回適當的鏽蝕對象。我想說,每個讀者都可以作爲一個迭代器來操作,產生該對象。

下面的代碼

/// A generic trait for reading u32s 
trait MyReader { 
    fn get_next(&mut self) -> Option<u32>; 
} 

/// Which means we should be able to iterate over the reader, yielding u32s 
impl Iterator for MyReader { 
    type Item = u32; 
    fn next(&mut self) -> Option<u32> { 
     self.get_next() 
    } 
} 

/// Example of a 'reader' 
struct MyVec { 
    buffer: Vec<u32>, 
} 

/// This can act as a reader 
impl MyReader for MyVec { 
    fn get_next(&mut self) -> Option<u32> { 
     self.buffer.pop() 
    } 
} 

fn main() { 
    // Create a reader 
    let mut veccy = MyVec { buffer: vec![1, 2, 3, 4, 5] }; 

    // Doesn't work :(
    let res = veccy.next(); 
} 

編譯器輸出:

rustc 1.15.0 (10893a9a3 2017-01-19) 
error: no method named `next` found for type `MyVec` in the current scope 
    --> <anon>:31:21 
    | 
31 |  let res = veccy.next(); 
    |      ^^^^ 
    | 
    = help: items from traits can only be used if the trait is implemented and in scope; the following traits define an item `next`, perhaps you need to implement one of them: 
    = help: candidate #1: `std::iter::Iterator` 
    = help: candidate #2: `std::iter::ZipImpl` 
    = help: candidate #3: `std::str::pattern::Searcher` 

Here是上鏽操場的代碼。

在我看來,因爲MyVec實現了MyReader,那麼它應該可以用作迭代器,因此我應該可以在其上調用.next()。由於我實施了MyReader,因此我應該免費獲得Iterator的實施,對吧?行impl Iterator for ...顯示Iterator在範圍內,所以我不明白錯誤來自何處。

+0

另請參閱http://stackoverflow.com/q/34438755/155423和http://stackoverflow.com/q/29256519/155423。 – Shepmaster

回答

4

這條線不會做你認爲它的作用。

impl Iterator for MyReader { 

這實現Iteratortrait objectMyReader。你想要的是實現Iterator爲每個類型也實現MyReader。不幸的是,由於一致性規則,這是不可能的。

在Rust中,只能在定義特徵的箱子或定義要在其上實施的類型的箱子中實現特徵。 (泛型類型的東西有點複雜,但這是基本思想。)在這種情況下,Iterator是標準庫的一個特徵,因此您無法在任何您未定義的類型上實現它。如果你仔細想想,這是有道理的,否則如果其中一種類型的預先存在的實現是Iterator--哪一種會被使用?

一種解決方案是將實現MyReader的類型換成新類型,並在其上實現Iterator。由於您自己定義了新類型,因此您可以自由實施Iterator