iT邦幫忙

2023 iThome 鐵人賽

DAY 25
0

我們之前不管是在定義結構,或者是使用 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

其實不一定要使用 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

上一篇
Day 24 - Module part 2
下一篇
Day 26 - 泛型 part 2
系列文
成為程式界的 F1 賽車手,用 30 天認識 Rust 30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言