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

相关推荐
韩立学长17 分钟前
基于Springboot酒店管理系统的设计与实现c12044zy(程序、源码、数据库、调试部署方案及开发环境)系统界面展示及获取方式置于文档末尾,可供参考。
数据库·spring boot·后端
资深web全栈开发28 分钟前
深入理解 Google Wire:Go 语言的编译时依赖注入框架
开发语言·后端·golang
忘记92632 分钟前
什么是spring boot
java·spring boot·后端
expect7g35 分钟前
Paimon源码解读 -- Compaction-6.CompactStrategy
大数据·后端·flink
喵个咪1 小时前
开箱即用的 GoWind Admin|风行,企业级前后端一体中后台框架:极速搭建微服务应用
后端·微服务·go
qq_256247051 小时前
Rust 模块化单体架构:告别全局 Migrations,实现真正的模块自治
开发语言·架构·rust
分布式存储与RustFS1 小时前
MinIO替代方案与团队适配性分析:RustFS如何匹配不同规模团队?
人工智能·rust·开源项目·对象存储·minio·企业存储·rustfs
分布式存储与RustFS1 小时前
MinIO替代方案生态集成指南:RustFS如何无缝融入现代技术栈
rust·github·开源项目·对象存储·minio·企业存储·rustfs
十月南城1 小时前
多级缓存设计思路——本地 + 远程的一致性策略、失效风暴与旁路缓存的取舍
后端
float_六七1 小时前
Spring AOP连接点实战解析
java·后端·spring