我們之前不管是在定義結構,或者是使用 Function 時,
一旦定義了 type,一定就要使用那個 type
不過如果為了不同的型別寫了 重複且運算式都相同的程式碼,
這樣聽起來還蠻麻煩的
來舉個例子,假設我們要做個加法計算機
fn main() {
fn calculator(a: i32, b: i32) -> i32 {
a + b
}
let result = calculator(10, 100);
println!("{}", result)
}
> cargo run
110
參數是整數的話沒問題,因為我們型態定義成整數
但如果是浮點數呢?
fn main() {
fn calculator(a: i32, b: i32) -> i32 {
a + b
}
let result = calculator(10.1, 100.1);
println!("{}", result)
}
馬上就噴錯誤訊息了,因為傳進去的型態跟原本定義的型態不一致
> cargo run
error[E0308]: arguments to this function are incorrect
--> src/main.rs:6:18
|
6 | let result = calculator(10.1, 100.1);
| ^^^^^^^^^^ ---- ----- expected `i32`, found floating-point number
| |
| expected `i32`, found floating-point number
|
note: function defined here
--> src/main.rs:2:8
|
2 | fn calculator(a: i32, b: i32) -> i32 {
| ^^^^^^^^^^ ------ ------
這樣就有愧於加法計算機的名號了是吧?泛型的出現讓加法計算機得以流傳下去
泛型可以用來處理不同資料型態的數據,我們就不需要為了每個型態重複寫程式碼
來看看我們該怎麼改上面的範例,才能同時使用整數及浮點數
要注意的是,為了讓泛型可以使用 +
我們需要加上 std::ops::Add
這個 trait
fn main() {
fn calculator<T: std::ops::Add<Output = T>>(a: T, b: T) -> T {
a + b
}
}
這麼一來,使用浮點數就沒問題了
fn main() {
fn calculator<T: std::ops::Add<Output = T>>(a: T, b: T) -> T {
a + b
}
let result = calculator(10.1, 100.1);
println!("{}", result)
}
> cargo run
110.19999999999999
使用整數也沒問題哦!
fn main() {
fn calculator<T: std::ops::Add<Output = T>>(a: T, b: T) -> T {
a + b
}
let result = calculator(10, 100);
println!("{}", result)
}
> cargo run
110
其實不一定要使用 T ,你想叫 CCC 都可以,而 T 為 type 的字首,在其他程式語言也都會稱泛型為 T ,使用這個慣例會讓程式碼比較易懂
在結構中也能使用泛型,一樣要先聲明要使用泛型
fn main() {
struct dessert<T> {
name: String,
price: T,
}
let apple_pie = dessert {
name: "yummy apple pie".to_string(),
price: 11.9,
};
println!("{}'s price is {:?}", apple_pie.name, apple_pie.price)
}
> cargo run
yummy apple pie's price is 11.9
只要兩個取不同名稱就可以了
fn main() {
struct dessert<T, U> {
name: T,
price: U,
}
let apple_pie = dessert {
name: "yummy apple pie".to_string(),
price: 11.9,
};
println!("{}'s price is {:?}", apple_pie.name, apple_pie.price)
}
> cargo run
yummy apple pie's price is 11.9