《Effective Rust》第 5 条:理解类型转换

  • King
  • 更新于 2024-06-15 09:33
  • 阅读 800

第5条:理解类型转换Rust的类型转换分为三个类别:手动:通过实现From和Intotrait提供的用户定义类型转换半自动:使用as关键字在值之间进行显式转换自动:隐式强制转换为新类型本章节的重点主要是第一种,即手动转换类型,因为后两种大多数情况下不适用于用户定义类

第 5 条:理解类型转换

Rust 的类型转换分为三个类别:

  • 手动:通过实现 FromInto trait 提供的用户定义类型转换
  • 半自动:使用 as 关键字在值之间进行显式转换
  • 自动:隐式强制转换为新类型

本章节的重点主要是第一种,即手动转换类型,因为后两种大多数情况下不适用于用户定义类型的转换。但也有一些例外,所以本章节最后的部分将讨论转换和强制类型转换 —— 包括它们如何适用于用户定义的类型。

请注意,与许多较旧的语言不同,Rust 在数值类型之间不会执行自动转换。这甚至适用于整数类型的“安全”转换:

let x: u32 = 2;
let y: u64 = x;
error[E0308]: mismatched types
  --> src/main.rs:70:18
   |
70 |     let y: u64 = x;
   |            ---   ^ expected `u64`, found `u32`
   |            |
   |            expected due to this
   |
help: you can convert a `u32` to a `u64`
   |
70 |     let y: u64 = x.into();
   |                   +++++++

用户定义类型转换

与语言的其他特性([第 10 条])一样,在不同用户定义类型值之间执行转换的能力被封装为标准 trait —— 或者更确切地说,是一组相关的泛型 trait

表达类型值转换能力的四个相关 trait 如下:

  • From<T>:这种类型的项可以由类型 T 的项构建,并且转换总是成功。
  • TryFrom<T>:这种类型的项可以由类型 T 的项构建,但转换可能不会成功。
  • Into<T>:这种类型的项可以转换为类型 T 的项,并且转换总是成功。
  • TryInto<T>:这种类型的项可以转换为类型 T 的项,但转换可能不会成功。

鉴于[第 1 条]中关于在类型系统中表达事物的讨论,发现 Try... 变体的区别在于,唯一的 trait 方法返回一个 Result 而不是保证的新项。Try... trait 定义还要求一个关联类型,它给出了失败情况下发出的错误 E 的类型。

因此,第一条建议是,如果可能转换失败,则实现(仅)Try... trait,与[第 4 条] 一致。另一种方法是忽略错误的可能性(例如,使用 .unwrap(),但这需要是深思熟虑的选择,在大多数情况下,最好将这个选择留给调用者。

类型转换 trait 具有明显的对称性:如果类型 T 可以转换为类型 U(通过 Into<U>),难道这不等于可以通过从类型 T 的项转换来创建类型 U 的项(通过 From<T>)吗?

确实如此,这导致了第二条建议:为转换实现 From traitRust 标准库必须在这两个可能性中选择一个,以防止系统在眩晕的圆圈中旋转,[^1] 它选择了自动提供 From 实现的 Into

如果你正在使用这两个 trait 中的一个,作为你自己新的泛型的 trait 约束,那么建议是相反的:trait 约束使用 Into trait。这样,约束将同时满足直接实现 Into 的内容和仅直接实现 From 的内容。

FromInto 的文档强调了这种自动转换,但阅读标准库代码的相关部分也值得一读,这是一个泛型 trait 实现:

impl<T, U> Into<U> for T
where
    U: From<T>,
{
    fn into(self) -> U {
        U::from(self)
    }
}

trait 规范翻译成文字可以帮助理解更复杂的 trait 约束。在这个案例中,它相当简单:"只要 U 已经实现了 From<T>,我就可以为类型 T 实现 Into<U>"。

标准库还包括了为标准库类型实现这些转换 trait 的各种情况。正如你所预期的,对于整数转换,当目标类型包括源类型的所有可能值时(例如,u64From<u32>),会有 From 实现,而当源值可能不适合目标时(例如,u32TryFrom<u64>),会有 TryFrom 实现。

除了前面显示的 Into 版本的泛型 trait 实现之外,还有各种其他的泛型 trait 实现主要用于智能指针类型,允许智能指针从其持有的类型的实例自动构造。这意味着接受智能指针参数的泛型方法也可以用普通的旧项调用;更多内容将在后续介绍和[第 8 条]中展开。

TryFrom trait 还有一个泛型实现,适用于任何已经以...

剩余50%的内容订阅专栏后可查看

点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
King
King
0x56af...a0dd
擅长Rust/Solidity/FunC/Move开发