两个重要的特征(trait),它们为类型之间的转换提供了强大而灵活的机制
From 特征
From 特征用于定义一个类型如何从另一个类型转换而来
pub trait From<T> {
fn from(T) -> Self;
}
T 是源类型,也就是要转换的类型
Self 是目标类型,即转换后的类型
当一个类型实现了 From<T>
特征时,就意味着该类型可以从 T 类型转换得到
Into 特征
Into 特征用于定义一个类型可以转换为另一个类型
pub trait Into<T> {
fn into(self) -> T;
}
T 是目标类型
self 是源类型的实例,通过调用 into() 方法将自身转换为目标类型 T
两者关系
在 Rust 中,如果一个类型实现了 From<T>
特征,那么 Rust 会自动为其实现 Into<T>
特征
这是因为 Into 特征的实现可以基于 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);
let num2: Number = 30.into();
println!("{:?}, {:?}", num, num2);
}
Number 类型实现了 From<i32>
特征,因此可以使用 Number::from(30)
进行转换,同时也可以使用 30.into()
进行转换,因为 Rust 自动为 Number 实现了 Into<Number>
特征
使用场景
From 特征
当希望一个类型能够从另一个类型方便地创建时,使用 From 特征。例如,将 &str
转换为 String
:
let s: String = String::from("hello");
Into 特征
当有一个值,想要将其转换为另一个类型时,使用 Into 特征:
fn takes_string(s: String) {
println!("Received: {}", s);
}
let s = "hello";
takes_string(s.into());
快速记忆技巧
From:来源导向:
可以把 From 理解为 “从哪里来”,即目标类型是从源类型转换而来的。就像 String::from("hello")
表示字符串是从 &str
类型转换得到的。想象成一个箭头,从源类型指向目标类型,数据的流动方向是从源到目标。
Into:目标导向:
Into 可以理解为 “进入到哪里去”,即源类型的值要进入到目标类型中。例如 s.into()
表示 s 要转换为另一个类型。把它想象成一个容器,源类型的值要进入到目标类型这个容器中。
通过记住 “From 是从哪来,Into 是到哪去”,可以快速区分和理解这两个特征的用途
同时,要记住它们之间的自动实现关系,实现了 From 就自动拥有了 Into 的能力