Rust特征学习:From和Into特征
本节课我们来看一下与类型转换的有关的两个特征。
在Rust中,From
和 Into
是两个用于类型转换的特征(traits)。它们允许你在不同类型之间进行转换,提供了一种灵活的方式来处理类型之间的转换。
我们把实现该特征的对象叫实现者。
- From特征是将目标对象转换为实现者。
- Into特征是将实现者转换为目标对象。
- 实现者实现了From特征,目标对象就自动实现Into特征。
From 特征:
From
特征定义了一个用于从一种类型转换为另一种类型的函数。它有一个方法 from
,需要实现这个方法来执行类型转换。
pub trait From<T>: Sized {
fn from(value: T) -> Self;
}
例如,假设我们有一个结构体 Person
:
struct Person {
name: String,
age: u32,
}
我们可以实现 From
特征来从字符串创建一个 Person
:
impl From<&str> for Person {
fn from(s: &str) -> Self {
// s的格式如:"Alice,30"
let parts: Vec<&str> = s.split(',').collect();
let name = parts[0].to_string();
let age = parts[1].parse().unwrap();
Person { name, age }
}
}
现在,我们可以使用 from
方法从 &str
类型创建 Person
类型:
let person: Person = Person::from("Alice,30");
在标准库中,有一些类似的实现,例如我们经常使用的String::from("oskwg.org")
。
Into 特征:
Into
特征是与 From
相反的,它定义了一个用于将类型转换为另一种类型的方法 into
。
pub trait Into<T>: Sized {
fn into(self) -> T;
}
使用上述的 Person
结构体,我们可以实现 Into
特征来将 Person
转换为 String
:
impl Into<String> for Person {
fn into(self) -> String {
format!("{} ({} years old)", self.name, self.age)
}
}
现在,我们可以使用 into
方法将 Person
转换为 String
:
let person = Person { name: "Bob".to_string(), age: 25 };
let person_string: String = person.into();
实现了From
特征的类型,自动也实现了 Into
特征
之所以能够自动实现Into特征的原因是如下代码:
// src/convert/mod.rs
impl<T, U> Into<U> for T
where
U: From<T>,
{
fn into(self) -> U {
U::from(self)
}
}
标准库中这段代码的意思是,为T类型实现了Into特征,可以将T类型转换为U类型。where后面限定了U类型,只有实现了From<T>特征的U类型才能转换。
示例:
struct User {
login_name: String,
}
struct Student {
first_name: String,
last_name: String,
}
impl From<Student> for User {
fn from(Student { first_name, last_name }: Student) -> Self {
User { login_name: format!("{first_name} {last_name}") }
}
}
// impl Into<User> for Student {
// fn into(self) -> User {
// User::from(self)
// }
// }
fn main() {
let student = Student { first_name: String::from("oskwg"), last_name: String::from("org") };
// let user = User::from(student);
let x: User = student.into();
println!("{:?}",x)
}
在这个例子中,我们需要把Student转换为User,那么学生就具有了用户登录名,为此我们为User
实现了 From<Student>
,此时Student类型正好符合了src/convert/mod.rs
中泛型的这段代码,所以 Into<User>
也就自动实现了,使得我们可以使用 into
方法进行类型转换,而不必显式实现 Into<User>
。这样的设计简化了代码,提高了可读性和可维护性。
转载自:https://juejin.cn/post/7338053219993911346