Rust特征学习:From和Into特征

本节课我们来看一下与类型转换的有关的两个特征。

在Rust中,FromInto 是两个用于类型转换的特征(traits)。它们允许你在不同类型之间进行转换,提供了一种灵活的方式来处理类型之间的转换。

我们把实现该特征的对象叫实现者。

  1. From特征是将目标对象转换为实现者。
  2. Into特征是将实现者转换为目标对象。
  3. 实现者实现了From特征,目标对象就自动实现Into特征。

From 特征:

From 特征定义了一个用于从一种类型转换为另一种类型的函数。它有一个方法 from,需要实现这个方法来执行类型转换。

rust 复制代码
pub trait From<T>: Sized {
    fn from(value: T) -> Self;
}

例如,假设我们有一个结构体 Person

rust 复制代码
struct Person {
    name: String,
    age: u32,
}

我们可以实现 From 特征来从字符串创建一个 Person

rust 复制代码
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 类型:

rust 复制代码
let person: Person = Person::from("Alice,30");

在标准库中,有一些类似的实现,例如我们经常使用的String::from("oskwg.org")

Into 特征:

Into 特征是与 From 相反的,它定义了一个用于将类型转换为另一种类型的方法 into

rust 复制代码
pub trait Into<T>: Sized {
    fn into(self) -> T;
}

使用上述的 Person 结构体,我们可以实现 Into 特征来将 Person 转换为 String

rust 复制代码
impl Into<String> for Person {
    fn into(self) -> String {
        format!("{} ({} years old)", self.name, self.age)
    }
}

现在,我们可以使用 into 方法将 Person 转换为 String

rust 复制代码
let person = Person { name: "Bob".to_string(), age: 25 };
let person_string: String = person.into();

实现了From特征的类型,自动也实现了 Into 特征

之所以能够自动实现Into特征的原因是如下代码:

rust 复制代码
// 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类型才能转换。

示例:

rust 复制代码
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>。这样的设计简化了代码,提高了可读性和可维护性。

相关推荐
BYSJMG5 分钟前
计算机毕业设计选题推荐:基于Hadoop的城市交通数据可视化系统
大数据·vue.js·hadoop·分布式·后端·信息可视化·课程设计
BYSJMG14 分钟前
Python毕业设计选题推荐:基于大数据的美食数据分析与可视化系统实战
大数据·vue.js·后端·python·数据分析·课程设计·美食
东东51623 分钟前
OA自动化居家办公管理系统 ssm+vue
java·前端·vue.js·后端·毕业设计·毕设
程序员鱼皮38 分钟前
前特斯拉 AI 总监:AI 编程最大的谎言,是 “提效”
前端·后端·ai·程序员·开发
好好研究1 小时前
SpringBoot使用外置Tomcat
spring boot·后端·tomcat
索荣荣2 小时前
Spring Boot 实现DOCX转PDF(基于docx4j的轻量级开源方案)
spring boot·后端·pdf
mit6.8242 小时前
[todo]10个常见的后端框架
后端
没有bug.的程序员2 小时前
Spring Boot 与 Sleuth:分布式链路追踪的集成、原理与线上故障排查实战
java·spring boot·分布式·后端·分布式链路追踪·sleuth·线上故障排查
爱敲代码的憨仔2 小时前
Spring-AOP
java·后端·spring
短剑重铸之日2 小时前
《设计模式》第四篇:观察者模式
java·后端·观察者模式·设计模式