FromInto

FromInto 这两个 trait 本质上是相互关联的,这实际上是它们实现的一部分。如果你能够将类型 B 转换为类型 A,那么我们应该很容易相信我们可以将类型 A 转换为类型 B。

From

From trait 允许一个类型定义如何从另一个类型创建自身,从而为多种类型之间的转换提供了一种非常简单的机制。标准库中有很多针对原始类型和常用类型转换的此 trait 的实现。

例如,我们可以很容易地将 str 转换为 String

#![allow(unused)]
fn main() {
let my_str = "hello";
let my_string = String::from(my_str);
}

我们可以为我们自己的类型定义一个类似的转换。

use std::convert::From;

#[derive(Debug)]
struct Number {
    value: i32,
}

impl From<i32> for Number {
    fn from(item: i32) -> Self {
        Number { value: item }
    }
}

fn main() {
    let num = Number::from(30);
    println!("My number is {:?}", num);
}

Into

Into trait 只是 From trait 的倒数。它定义了如何将一个类型转换为另一个类型。

调用 into() 通常需要我们指定结果类型,因为编译器大多数时候无法确定这一点。

use std::convert::Into;

#[derive(Debug)]
struct Number {
    value: i32,
}

impl Into<Number> for i32 {
    fn into(self) -> Number {
        Number { value: self }
    }
}

fn main() {
    let int = 5;
    // Try removing the type annotation
    let num: Number = int.into();
    println!("My number is {:?}", num);
}

FromInto 是可互换的

FromInto 被设计为互补的。我们不需要为这两个 trait 都提供实现。如果你为你的类型实现了 From trait,Into 将在必要时调用它。但是请注意,反之则不然:为你的类型实现 Into 并不会自动为其提供 From 的实现。

use std::convert::From;

#[derive(Debug)]
struct Number {
    value: i32,
}

// Define `From`
impl From<i32> for Number {
    fn from(item: i32) -> Self {
        Number { value: item }
    }
}

fn main() {
    let int = 5;
    // use `Into`
    let num: Number = int.into();
    println!("My number is {:?}", num);
}