欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

生锈类型转换 "作为, 从, 进入

最编程 2024-03-11 15:43:18
...

「这是我参与11月更文挑战的第 18 天,活动详情查看:2021最后一次更文挑战


Rust的这一特殊功能是我在Bevy示例代码中经常看到的,特别是在涉及到颜色的时候,例如:

materials.add(Color::rgb(0.7, 0.7, 0.7).into())

.into() 我想了很多,不过终于能够搞清楚它的作用。好吧,至少我认为我弄明白了。

as

Rust中简单的(显式)类型转换或铸造可以用as关键字来完成:

fn main() {
  let num:u8 = 10;
  let multiplied = times_ten(num as f32);

  println!("{}", multiplied); // 100
}

fn times_ten(val: f32) -> f32 {
  val * 10.0
}

From

在Rust中,From 是类型转换的两个 trait 之一。

假设我想创建我自己的特殊类型,叫做 MySpecialNumber,并想把一个现有的u32变量转换为我的自定义类型,我会这样做的:

#[derive(Debug)] // needed because struct displays nothing so needs to have a debug view
struct MySpecialNumber(u32);

impl From<u32> for MySpecialNumber {
  fn from(num: u32) -> Self {
    MySpecialNumber(num)
  }
}

fn main() {
  let existing_var = 30;
  let num = MySpecialNumber::from(existing_var);
  println!("{:?}", num); // Prints -> MySpecialNumber(30)
}

如果这是你第一次再看到 struct 或 impl 关键字,不要担心。我打算在以后的文章中介绍这些。不过如果你来自Javascript,你可以把它们看成是制造对象的一种稍微复杂的方式。

上面的代码片段使用上面写的 from(),将u32类型的 existing_var 改为 MySpecialNumber 类型。

因为From方法扩展了一个trait,它必须以一种非常特殊的方式来写才能工作。如果我把fn from(num: u32) 这一行改成 fn from(num: f32),它就不会工作。From trait的源代码可以在 Rust Github repo 上找到。

Into

Into是Rust中第二个用于类型转换的trait。它的工作方向与From特质相反,不是从y创建x,而是将y转化为x,有意义吗?这有点令人困惑。我觉得代码是解释事情的最好方式。

First way

如果已经有了From trait的实现,我们也可以使用 Into trait,这非常方便。

要使用into,上面的代码片段的主函数可以重新写成:

...

fn main() {
  let existing_var: u32 = 30;
  let num: MySpecialNumber = existing_var.into();
  println!("{:?}", num); // Prints -> MySpecialNumber(30)
}

可以说这是更可读的。existing_var 被转换为 MySpecialNumber 是因为它被添加了一个类型注释。如果这个类型标记被删除,Rust将不知道该把现有变量转换为什么类型。

let num = existing_var.into(); // this won't work

如果你真的想,你可以用Rust源代码中的Into方法写一个完整的Into方法,类似于我上面写的From方法,但我认为From已经足够好了。

推荐阅读