Rust学习之——From Trait和Into Trait以及“类型”到字符串的转换

2024-02-29 10:08

本文主要是介绍Rust学习之——From Trait和Into Trait以及“类型”到字符串的转换,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一次奇怪的实践

今天看了一个demo,为自定义类型到String类型的转换实现了From Trait下的from方法,但是是调用into方法来执行该转换。一开始就觉得很离谱。具体如下所示:

struct OriginType{value: String,
}impl From<OriginType> for TargetType {fn from (t: OriginType) -> TargetType  {省略}
}let o: OriginType = OriginType::new("asdad");
let t: TargetType = o.into();

然后查了资料,发现From和Into这两个Trait是一对,经常在一起出现,但是为什么实现from方法却可以直接用into调用呢?

于是我提出了如下的几个问题:

  1. 为什么可以为类型实现From中的from方法,却用的是从来没有出现过的into方法?
  2. 那么Into Trait是干什么用的?

先回答第一个问题

Used to do value-to-value conversions while consuming the input value. It is the reciprocal of Into.

One should always prefer implementing From over Into because implementing From automatically provides one with an implementation of Into thanks to the blanket implementation in the standard library.

根据官网的描述,From和Into这两个Trait是互为相反的(reciprocal)。并且人们应该更喜欢优先实现From,因为实现From会自动提供Into的实现,这要归功于标准库中的一揽子(blanket)实现。

第二个问题

Only implement Into when targeting a version prior to Rust 1.41 and converting to a type outside the current crate. From was not able to do these types of conversions in earlier versions because of Rust’s orphaning rules. See Into for more details.

Into Trait只在Rust1.41之前,并且用于把一个类型转换为当前crate之外的类型(例如标准库中的Vec或外部库中的类型)。这是因为Rust有孤儿规则,不能去改动外部的,或者说是当前crate之外的类型,而From在早期的版本中无法做到这些类型之间的转换。

Prefer using Into over using From when specifying trait bounds on a generic function. This way, types that directly implement Into can be used as arguments as well.

当在泛型函数上指定Trait bounds时,应该优先使用Into。稍后将在Into的用法中详细介绍。

From Trait

From Trait 用于提供值与值之间的转换(从类型OriginType到另一个类型TargetType)。

pub trait From<T> {fn from(T) -> Self;
}

要为TargetType实现From,必须实现的方法是from。看下面的一个例子:

impl From<OriginType> for TargetType {fn from(value: OriginType) -> Self {// pass// 返回一个TargetType的实例}
}let o: OriginType;
// 这两种方法都可以,第一种方法可以自动推断类型,因此不需要类型注解
// 第二种方法由于使用了into方法,而且一个类型可以转换为多个其他类型,因此必须进行类型注解
let t = TargetType::from(o);
let t: TargetType = o.into();

实例:下面的代码片段就是从字符串的HTTP请求 转换为 为带有数据结构的、便于查询的HttpRequest的结构体类型。

impl From<String> for HttpRequest {fn from (req: String) -> Self {return HttpRequest {method: parsed_method(req),resource: parsed_resource(req),version: parsed_version(req),headers: parsed_headers(req),body: parsed_body(req),}}
}let req_string: String = String::from_utf8(read_buffer.to_vec()).unwrap();
// 有两种方法第一种是实现的from方法,第二种是自动对应的Into实现的into方法
// 第一种方法可以自动推断类型,因此可以不写类型注解
// 第二种方法使用了into方法,而且一个类型可以转换为多个其他类型,因此必须进行类型注解
let http_request = HttpRequest::from(req_string);
let http_request: HttpRequest = req_string.into();

再说Into Trait

之前说了,在Rust1.41之前,如果目标类型不是当前crate中的一部分,那么不能直接实现From方法,例如使用以下的代码:

在下面的代码片段中,Wrapper是一个自定义的元组结构体,用于存放类型T的向量,而目标类型Vec<T>是标准库中的类型。

struct Wrapper<T>(Vec<T>);impl<T> From<Wrapper<T>> for Vec<T> {fn from(w: Wrapper<T>) -> Vec<T> {w.0}
}

这段代码在旧版本中会编译失败,这是因为Rust的孤儿规则曾经更严格一些。要绕过这个,可以尝试实现Into:

impl Into<TargetType> for OriginType {fn into(value: OriginType) -> TargetType {// 返回TargetType类型的值}
}
struct Wrapper<T>(Vec<T>);impl<T> Into<Vec<T>> for Wrapper<T> {fn into(self) -> Vec<T> {self.0}
}

重要的是要了解 Into 不提供 From 实现( From 却提供 Into)。因此,应该始终尝试先实现 From,如果 From 无法实现,则再尝试使用 Into

标准库中的String类型就实现了Into<Vec<u8>>:is_hello的参数表示可以接收任意一个能够转换为Vec<u8>的类型。

fn is_hello<T: Into<Vec<u8>>>(s: T) {let bytes = b"hello".to_vec();assert_eq!(bytes, s.into());
}let s = "hello".to_string();
is_hello(s);

注意事项

From和Into实现的转换不允许出现错误,即转换过程不能抛出异常。如果转换过程允许抛出异常请使用:TryFrom和TryInto。

这篇关于Rust学习之——From Trait和Into Trait以及“类型”到字符串的转换的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/758409

相关文章

Oracle数据库常见字段类型大全以及超详细解析

《Oracle数据库常见字段类型大全以及超详细解析》在Oracle数据库中查询特定表的字段个数通常需要使用SQL语句来完成,:本文主要介绍Oracle数据库常见字段类型大全以及超详细解析,文中通过... 目录前言一、字符类型(Character)1、CHAR:定长字符数据类型2、VARCHAR2:变长字符数

C#数据结构之字符串(string)详解

《C#数据结构之字符串(string)详解》:本文主要介绍C#数据结构之字符串(string),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录转义字符序列字符串的创建字符串的声明null字符串与空字符串重复单字符字符串的构造字符串的属性和常用方法属性常用方法总结摘

Spring Boot 配置文件之类型、加载顺序与最佳实践记录

《SpringBoot配置文件之类型、加载顺序与最佳实践记录》SpringBoot的配置文件是灵活且强大的工具,通过合理的配置管理,可以让应用开发和部署更加高效,无论是简单的属性配置,还是复杂... 目录Spring Boot 配置文件详解一、Spring Boot 配置文件类型1.1 applicatio

Java实现时间与字符串互相转换详解

《Java实现时间与字符串互相转换详解》这篇文章主要为大家详细介绍了Java中实现时间与字符串互相转换的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、日期格式化为字符串(一)使用预定义格式(二)自定义格式二、字符串解析为日期(一)解析ISO格式字符串(二)解析自定义

在java中如何将inputStream对象转换为File对象(不生成本地文件)

《在java中如何将inputStream对象转换为File对象(不生成本地文件)》:本文主要介绍在java中如何将inputStream对象转换为File对象(不生成本地文件),具有很好的参考价... 目录需求说明问题解决总结需求说明在后端中通过POI生成Excel文件流,将输出流(outputStre

python+opencv处理颜色之将目标颜色转换实例代码

《python+opencv处理颜色之将目标颜色转换实例代码》OpenCV是一个的跨平台计算机视觉库,可以运行在Linux、Windows和MacOS操作系统上,:本文主要介绍python+ope... 目录下面是代码+ 效果 + 解释转HSV: 关于颜色总是要转HSV的掩膜再标注总结 目标:将红色的部分滤

利用Python开发Markdown表格结构转换为Excel工具

《利用Python开发Markdown表格结构转换为Excel工具》在数据管理和文档编写过程中,我们经常使用Markdown来记录表格数据,但它没有Excel使用方便,所以本文将使用Python编写一... 目录1.完整代码2. 项目概述3. 代码解析3.1 依赖库3.2 GUI 设计3.3 解析 Mark

C语言中的数据类型强制转换

《C语言中的数据类型强制转换》:本文主要介绍C语言中的数据类型强制转换方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C语言数据类型强制转换自动转换强制转换类型总结C语言数据类型强制转换强制类型转换:是通过类型转换运算来实现的,主要的数据类型转换分为自动转换

python中字符串拼接的几种方法及优缺点对比详解

《python中字符串拼接的几种方法及优缺点对比详解》在Python中,字符串拼接是常见的操作,Python提供了多种方法来拼接字符串,每种方法有其优缺点和适用场景,以下是几种常见的字符串拼接方法,需... 目录1. 使用 + 运算符示例:优缺点:2. 使用&nbsjsp;join() 方法示例:优缺点:3

java字符串数字补齐位数详解

《java字符串数字补齐位数详解》:本文主要介绍java字符串数字补齐位数,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java字符串数字补齐位数一、使用String.format()方法二、Apache Commons Lang库方法三、Java 11+的St