有時,當你編寫函數或數據類型時,我們可能會希望它能處理多種類型的參數。幸運的是,Rust有一個能給我們更好選擇的功能:泛型。泛型在類型理論中叫做_參數多態_(_parametric polymorphism_),它意味著他們是對于給定參數(parametric)能夠有多種形式(`poly`是多,`morph`是形態)的函數或類型。
不管怎么樣,類型理論就說這么多,現在我們來看些泛型代碼。Rust標準庫提供了一個類型,`Option`,它是泛型的:
~~~
enum Option<T> {
Some(T),
None,
}
~~~
``部分,你可能見過幾次了,代表它是一個泛型數據類型。在我們枚舉聲明中,每當我們看到`T`,我們用這個類型代替我們泛型中使用的類型。下面是一個使用`Option`的例子,它帶有額外的類型標注:
~~~
let x: Option<i32> = Some(5);
~~~
在類型聲明中,我們看到`Option`。注意它與`Option`的相似之處。所以在這個特定的`Option`中,`T`是`i32`。在綁定的右側,我們用了`Some(T)`,`T`是`5`。因為那是個`i32`,兩邊類型相符,所以皆大歡喜。如果不相符,我們會得到一個錯誤:
~~~
let x: Option<f64> = Some(5);
// error: mismatched types: expected `core::option::Option<f64>`,
// found `core::option::Option<_>` (expected f64 but found integral variable)
~~~
這并不是意味著我們不能寫一個`f64`的`Option`!只是類型必須相符:
~~~
let x: Option<i32> = Some(5);
let y: Option<f64> = Some(5.0f64);
~~~
這樣就好了。一個定義,多種用途。
不一定只有一個類型是泛型的。考慮下Rust內建的`Result`類型:
~~~
enum Result<T, E> {
Ok(T),
Err(E),
}
~~~
這里有兩個泛型類型:`T`和`E`。另外,大寫字母可以是任何你喜歡的(大寫)字母。我們可以定義`Result`為:
~~~
enum Result<A, Z> {
Ok(A),
Err(Z),
}
~~~
如果你想這么做的話。慣例告訴我們第一個泛型參數應該是`T`,代表`type`,然后我們用`E`來代表`error`。然而,Rust并不管這些。
`Result`意圖作為計算的返回值,并為了能夠在不能工作時返回一個錯誤。
## 泛型函數
我們可以用熟悉的語法編寫一個獲取泛型參數的函數:
~~~
fn takes_anything<T>(x: T) {
// do something with x
}
~~~
語法有兩部分:``代表“這個函數帶有一個泛型類型”,而`x: T`代表“`x`是`T`類型的”。
多個參數可以有相同的泛型類型:
~~~
fn takes_two_of_the_same_things<T>(x: T, y: T) {
// ...
}
~~~
我們可以寫一個獲取多個(泛型)類型的版本:
~~~
fn takes_two_things<T, U>(x: T, y: U) {
// ...
}
~~~
泛型函數結合“特性約束”時最有用,我們會在[特性部分](http://doc.rust-lang.org/nightly/book/traits.html)涉及到它。
## 泛型結構體(Generic structs)
你也可以在一個`struct`中儲存泛型類型:
~~~
struct Point<T> {
x: T,
y: T,
}
let int_origin = Point { x: 0, y: 0 };
let float_origin = Point { x: 0.0, y: 0.0 };
~~~
與函數類似,``是我們聲明的泛型參數,而我們也接著在類型定義中使用`x: T`。
- 前言
- 1.介紹
- 2.準備
- 2.1.安裝Rust
- 2.2.Hello, world!
- 2.3.Hello, Cargo!
- 3.學習Rust
- 3.1.猜猜看
- 3.2.哲學家就餐問題
- 3.3.其它語言中的Rust
- 4.高效Rust
- 4.1.棧和堆
- 4.2.測試
- 4.3.條件編譯
- 4.4.文檔
- 4.5.迭代器
- 4.6.并發
- 4.7.錯誤處理
- 4.8.外部語言接口
- 4.9.Borrow 和 AsRef
- 4.10.發布途徑
- 5.語法和語義
- 5.1.變量綁定
- 5.2.函數
- 5.3.原生類型
- 5.4.注釋
- 5.5.If語句
- 5.6.for循環
- 5.7.while循環
- 5.8.所有權
- 5.9.引用和借用
- 5.10.生命周期
- 5.11.可變性
- 5.12.結構體
- 5.13.枚舉
- 5.14.匹配
- 5.15.模式
- 5.16.方法語法
- 5.17.Vectors
- 5.18.字符串
- 5.19.泛型
- 5.20.Traits
- 5.21.Drop
- 5.22.if let
- 5.23.trait對象
- 5.24.閉包
- 5.25.通用函數調用語法
- 5.26.包裝箱和模塊
- 5.27.`const`和`static`
- 5.28.屬性
- 5.29.`type`別名
- 5.30.類型轉換
- 5.31.關聯類型
- 5.32.不定長類型
- 5.33.運算符和重載
- 5.34.`Deref`強制多態
- 5.35.宏
- 5.36.裸指針
- 6.Rust開發版
- 6.1.編譯器插件
- 6.2.內聯匯編
- 6.3.不使用標準庫
- 6.4.固有功能
- 6.5.語言項
- 6.6.鏈接參數
- 6.7.基準測試
- 6.8.裝箱語法和模式
- 6.9.切片模式
- 6.10.關聯常量
- 7.詞匯表
- 8.學院派研究
- 勘誤