疊代器和擁有權
Rust 的擁有權模型會影響許多 API。Iterator
和 IntoIterator
特徵就是一例。
Iterator
特徵就像介面一樣,可以說明型別的行為 (方法)。Iterator
特徵就是指您可以呼叫 next
,直到取回 None
為止:
#![allow(unused)] fn main() { pub trait Iterator { type Item; fn next(&mut self) -> Option<Self::Item>; } }
您可以像下方這樣使用這個特徵:
fn main() { let v: Vec<i8> = vec![10, 20, 30]; let mut iter = v.iter(); println!("v[0]: {:?}", iter.next()); println!("v[1]: {:?}", iter.next()); println!("v[2]: {:?}", iter.next()); println!("No more items: {:?}", iter.next()); }
如要瞭解疊代器傳回的型別為何,不妨在這裡測試答案:
fn main() { let v: Vec<i8> = vec![10, 20, 30]; let mut iter = v.iter(); let v0: Option<..> = iter.next(); println!("v0: {v0:?}"); }
思考一下,為什麼會使用這種型別?
IntoIterator
Iterator
特徵會告訴您如何在建立疊代器後進行「疊代」。相關特徵 IntoIterator
則會說明如何建立疊代器:
#![allow(unused)] fn main() { pub trait IntoIterator { type Item; type IntoIter: Iterator<Item = Self::Item>; fn into_iter(self) -> Self::IntoIter; } }
這裡的語法表示每個 IntoIterator
的實作都必須宣告兩種型別:
Item
:進行疊代的型別,例如i8
。IntoIter
:into_iter
方法傳回的Iterator
型別。
請注意,IntoIter
和 Item
已建立連結:疊代器必須具有相同的 Item
型別,表示會傳回 Option<Item>
。
和先前一樣,思考疊代器傳回的型別為何。
fn main() { let v: Vec<String> = vec![String::from("foo"), String::from("bar")]; let mut iter = v.into_iter(); let v0: Option<..> = iter.next(); println!("v0: {v0:?}"); }
for
迴圈
現在我們已瞭解 Iterator
和 IntoIterator
,可以建構 for
迴圈了。這會在運算式上呼叫 into_iter()
,並對產生的疊代器進行疊代:
fn main() { let v: Vec<String> = vec![String::from("foo"), String::from("bar")]; for word in &v { println!("word: {word}"); } for word in v { println!("word: {word}"); } }
思考一下,每個迴圈中的 word
型別為何?
請用上方的程式碼進行試驗,並參閱 impl IntoIterator for &Vec<T>
和 impl IntoIterator for Vec<T>
的說明文件確認答案。