Rust 中的 From 和 Into 特徵

如果你是 Rust 的新手,那麼 From 和 Into 特徵可能會讓你感到困惑,但它們是 Rust 有趣的特徵。在本文中,我們將通過例子學習 From 和 Into 特徵。

From 和 Into 特徵在本質上是相互關聯的,這實際上是其實現的一部分。如果你能把 B 型轉化爲 A 型,那麼我們很容易相信能把 A 型轉化爲 B 型。

From Trait

From 特徵提供了創建轉換特徵的能力,它允許你將一種類型的值轉換爲另一種類型的值。例如,標準庫實現了 “impl From<&'_ str> For String”,它允許你從 & str 生成 String。

例如,我們可以很容易地將 & str 轉換爲 String

let my_str = "Hello Intmain";
let my_string = String::from(my_str);

from trait 的另一個例子:假設我們想爲 SplitName 實現我們自己的 “From for SplitName”。這將允許我們將任何由空格分隔的給定名稱分割爲包含名字和姓氏的 Struct。這可以使用 From trait 輕鬆完成。

use std::convert::From;

#[derive(Debug)]
struct SplitName{
    first_name: String,
    last_name: String,
}

impl From<String> for SplitName {
    fn from(item: String) -> Self {

        let name_vector:Vec<&str> = item.split_whitespace().collect();
        SplitName { first_name : name_vector[0].to_string(), last_name :name_vector[1].to_string()}
    }
}

fn main() {
    let from_example = SplitName::from("Int Main".to_string());
    println!("The name is {:?}", from_example);
}

輸出

The name is: SplitName { first_name: "Int", last_name: "Main" }

From 在執行錯誤處理時也非常有用。當構造一個可能失敗的函數時,返回類型通常爲 Result<T, E>。

注意:這個特徵一定不能失敗,From Trait 用於完美轉換。如果轉換可能失敗或不完美,請使用 TryFrom。

Into Trait

Into 特徵與 From 特徵相反。From 的實現自動提供了 Into trait 的實現,應該避免實現 Into trait,而是實現 From trait。

使用 Into trait 通常需要指定要轉換成的類型,因爲編譯器在大多數情況下無法確定。

例如,我們可以很容易地將 & str 轉換爲 String:

let my_str = "Hello Intmain";
let my_string :String = my_str.into();

再次以上面的例子爲例,將任何由空格分隔的給定名稱分割爲包含名字和姓氏的 Struct,我們可以在將給定名稱轉換爲字符串後直接調用. into() 來分割名稱。這裏我們需要提供如下規範:“let into_example:SplitName = "Int Main".to_string().into();”

下面是使用 From 和 into 特徵將一個名稱轉換爲 SplitName 的完整代碼:

use std::convert::From;

#[derive(Debug)]
struct SplitName{
    first_name: String,
    last_name: String,
}

impl From<String> for SplitName {
    fn from(item: String) -> Self {

        let name_vector:Vec<&str> = item.split_whitespace().collect();
        SplitName { first_name : name_vector[0].to_string(), last_name :name_vector[1].to_string()}
    }
}

fn main() {
    let from_example = SplitName::from("Int Main".to_string());
    println!("The name is using from: {:?}", from_example);

    let into_example :SplitName = "Int Main".to_string().into();
    println!("TThe name is using into: {:?}", into_example);
}

輸出

The name is using from: SplitName { first_name: "Int", last_name: "Main" } 
The name is using into: SplitName { first_name: "Int", last_name: "Main" }

你可以自由地使用 into() 和 from(),由你決定哪一個對你的代碼最有表現力,但在指定泛型函數的特徵邊界時更傾向於使用 into 而不是 from,以確保僅實現 into 的類型也可以使用。

注意: 這個特徵一定不能失敗。如果轉換失敗,請使用 TryInto。

總結

Rust 中的 “From” 和“Into”特徵用於執行類型轉換。“From”特徵允許你通過實現 from 方法將一種類型的值轉換爲另一種類型的值。“Into”特徵是 “From” 特徵的簡化版本,並允許通過實現 into 方法進行更直接的轉換。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/Xq2XRKfeZs8Sip3EJZDS9A