《Rust By Example》 Conversion

68 阅读2分钟

初学者,若内容有任何问题,欢迎大佬在评论区纠正补充

From

Rust 标准库提供的 trait 提供了一种非常简单的机制来在多种类型之间进行转换

pub trait From<T>: Sized {
    /// Converts to this type from the input type.
    #[rustc_diagnostic_item = "from_fn"]
    #[must_use]
    #[stable(feature = "rust1", since = "1.0.0")]
    fn from(value: T) -> Self;
}

当然一个很简单的例子:我们可以使用 String::fromstr 转换为 String

fn main() {
    let str = "Hello Rust";
    let string = String::from(str);
    println!("{string}")
}

因为官方已经默认为 String 实现了 From trait 👇

#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
impl From<&str> for String {
    /// Converts a `&str` into a [`String`].
    ///
    /// The result is allocated on the heap.
    #[inline]
    fn from(s: &str) -> String {
        s.to_owned()
    }
}

所以我们可以自己为某些类型实现 From trait 来定义自己的类型转换

// 需求 将 i32 转为 Count

// 首先定义struct
#[derive(Debug)]
struct Count {
    value: i32,
}

// 为 Count 手动实现 From trait
impl From<i32> for Count {
    fn from(value: i32) -> Self {
        Count { value }
    }
}

fn main() {
    // 如何使用
    let count = Count::from(18);
    
    println!("{count:?}") // Count { value: 18 }
}

Into

Into 的作用和 from 类似,也可以实现类型转换

不过呢,编译器通常无法推断出转换完的类型,则需要自己手动标注 ❗❗

// 需求 将 i32 转为 Count

// 首先定义struct
#[derive(Debug)]
struct Count {
    value: i32,
}

// 为 i32 手动实现 Into trait
impl Into<Count> for i32 {
    fn into(self) -> Count {
        Count { value: self }
    }
}

fn main() {
    // 如何使用
    let c = 32;
    // 需要手动标注类型
    let c: Count = c.into();
    println!("{:?}", c) // Count { value: 32 }
}

From 和 Into 可以互换

已经为 Count 实现了 From trait,则对应的 i32 类型,就可以调用 into,无需再手动实现

反之如果为某个类型实现了 Into trait 则无法自动活动 from 方法 ❗❗

// 需求 将 i32 转为 Count

// 首先定义struct
#[derive(Debug)]
struct Count {
    value: i32,
}

// 为 Count 手动实现 From trait
impl From<i32> for Count {
    fn from(value: i32) -> Self {
        Count { value }
    }
}

fn main() {
    // 如何使用
    let count = Count::from(18);
    println!("{count:?}"); // Count { value: 18 }

    let num = 19;
    let count2: Count = num.into();
    println!("{count2:?}") // Count { value: 19 }
}

总结一下

方向性差异: From trait 定义了如何从其他类型转换到实现 From trait 的类型。而 Into trait 定义了如何将实现 Into trait 的类型转换到其他类型。