【Rust标准库中的convert(AsRef,From,Into,TryFrom,TryInto)】

Rust标准库中的convert(AsRef,From,Into,TryFrom,TryInto)

  • 为什么需要convert库
  • AsRef(不可变引用:多用于内部字段获取值)
  • From/Into Trait | TryFrom/TryInto Trait
      • From Trait:
      • TryFrom Trait:
    • From代码示例
    • Into使用方法示例
  • 总结


为什么需要convert库

在程序设计时,开发者一般会选择将一系列类型数据打包在一起,并有所限制,一是为了代码的简洁美观和复用,二是为了给予字段访问限制(如我们只通过初始化函数赋予字段值,外部程序需要引用到内部字段但不该修改它)
提到限制,会有开发者想到使用pub 关键字,没错,pub关键字可以将内部字段暴露给外部函数,但是破坏了封装性,且没有限制可变性,有人说我们可以自己写一个函数,也Ok,但是需要注意可变性的限制 ,一般情况下,我们都不希望外部程序可以通过除特定的方法之外修改我们的字段值。
Rust为开发者提供了一揽子转换方法,不论是从基础转为派生,还是反向转换均有trait,使用者只需实现trait,便可使用其中的转换方法并不失去封装性。

AsRef(不可变引用:多用于内部字段获取值)

假设有这样一种需求,某论坛需要获取登陆者的电话号码,以便在后续论坛举办活动时给会员发去活动邀请,所以我们就需要挑选合适的方式在代码中储存信息以及分析合理性。

  1. 我们需要一个struct元组来描述用户的电话号码(这里涉及到新类型模式,不展开了,仅以简单示例):
//UserInfo.rs
#[derive(Debug)]
pub struct Phone(String);
//我们实现了简单的new函数,并包含简单的号码正确性验证。
impl Phone {pub fn new(phone_number: &str) -> Result<Self, &'static str> {if phone_number.len() == 11 {Ok(Self(phone_number.to_string()))} else {Err("Invalid phone number")}}
}
//并将其封装到包mod.rs
pub(crate) mod UserInfo;

2.我们在main.rs,写一个sendmsg方法用以表示发送短信通知:

mod user_info;
use std::error::Error;use user_info::UserInfo::Phone;fn sendmsg(phonenum: &str) -> Result<String, Box<dyn Error>> {// Simulate a call to the phone number// For simplicity, we just return the number as a stringOk(phonenum.to_string())
}
fn main() {let result = Phone::new("13324533333");match result {Ok(phone) => sendmsg(phone.0),Err(e) => todo!(),};
}
//哪里会有问题?

没错,在sendmsg(phone.0) 时会有如下报错,field 0 of Phone is private
不论是将Phone中的String设置为pub,还是使用可变引用都破坏了我们代码的封装性。

正确地方法:实现trait AsRef:

//在UserInfo.rs中添加如下实现
impl AsRef<str> for Phone {fn as_ref(&self) -> &str {&self.0}
}//main.rs中使用入下调用
let result: Result<Phone, &str> = Phone::new("13324533333");let _ = match result {Ok(phone) => sendmsg(phone.as_ref()),Err(_e) => todo!(),};

如此,我们既不破坏封装性,又可以使用Rust convert的系列方法。

From/Into Trait | TryFrom/TryInto Trait

用以值到值的转换,简单来说,From提供细分内部类型向外部总类型转换,Into可以理解为为了适配孤儿规则而存在的,当前的版本1.82.0一般情况下不会有人主动实现Into,由于Rust的一揽子trait ,实现了From就等于实现了Into,非常方便。
不论是实际应用上,还是Rust中的举例来讲,From确实非常适合工程下的错误处理。
From有如下特点:

  1. 涉及到的转换不可以失败。
  2. 转换必须无损,如不丢失数据
  3. 转换必须保值,即不丢失精度
  4. 必须式是显而易见的转换,如 AuthError—> ServerError
//仅作代码示例
#[derive(Debug)]
enum ServerError {//总类型DatabaseError(String),//细分类型NetworkError(std::io::Error),TimeoutError(VarError),AuthError(Error),
}

ps: 如果不符合上述,则需要使用TryFrom,同样的,实现了TryFrom等于实现了TryInto。

From Trait:

pub trait From<T>: Sized {// Required methodfn from(value: T) -> Self;
}
//其直接返回类型。

TryFrom Trait:

pub trait TryFrom<T>: Sized {type Error;// Required methodfn try_from(value: T) -> Result<Self, Self::Error>;
}
//其返回Result,允许失败。

From代码示例

use std::{env::VarError,fmt::{Display, Error},
};
//仅作代码示例
#[derive(Debug)]
enum ServerError {DatabaseError(String),NetworkError(std::io::Error),TimeoutError(VarError),AuthError(Error),
}
impl Display for ServerError {fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {match self {ServerError::DatabaseError(err) => write!(f, "Database error: {}", err),ServerError::NetworkError(err) => write!(f, "Network error: {}", err),ServerError::TimeoutError(err) => write!(f, "Timeout error: {}", err),ServerError::AuthError(err) => write!(f, "AuthError error: {}", err),}}
}
impl From<String> for ServerError {fn from(err: String) -> Self {ServerError::DatabaseError(err)}
}impl From<std::io::Error> for ServerError {fn from(err: std::io::Error) -> Self {ServerError::NetworkError(err)}
}
impl From<Error> for ServerError {fn from(err: Error) -> Self {ServerError::AuthError(err)}
}impl From<VarError> for ServerError {fn from(err: VarError) -> Self {ServerError::TimeoutError(err)}
}fn handle_server_error() -> Result<(), String> {Err(String::from("handle_server_error"))
}
fn handle_server_error1() -> Result<(), std::io::Error> {Ok(())
}
fn handle_server_error2() -> Result<(), VarError> {Ok(())
}
fn handle_server_error3() -> Result<(), Error> {Ok(())
}fn func() -> Result<(), ServerError> {handle_server_error()?;handle_server_error1()?;handle_server_error2()?;handle_server_error3()?;Ok(())
}fn main() {match func() {Ok(_) => println!("Success"),Err(e) => eprintln!("Error: {:?}", e),}
}

如此,开发者既可以细分错误类型,并定制化输出内容,又可以统一result类型,并使用【?】将error向上抛出
同时,Rust也提供了thiserror,anyhow等错误处理包,通过扩展宏标记后,会生成大部分的样板代码,同时通过trace等方式,将上下文串联起来更加方便的排查问题。

Into使用方法示例

此示例代码来源于Rust By Example

use std::convert::Into;#[derive(Debug)]
struct Number {value: i32,
}impl Into<Number> for i32 {fn into(self) -> Number {Number { value: self }}
}fn main() {let int = 5;// Try removing the type annotationlet num: Number = int.into();println!("My number is {:?}", num);
}

总结

Rust中的转换,不仅仅使用方便,更重要的是可以告知阅读者我们在做什么。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/463842.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AprilTag在相机标定中的应用简介

1. AprilTag简介 相机标定用的标靶类型多样,常见的形式有棋盘格标靶和圆形标靶。今天要介绍的AprilTag比较特别,它是一种编码形式的标靶。其官网为AprilTag,它是一套视觉基准系统,包含标靶编解码方法(Tag生成)和检测算法(Tag检测),可用于AR、机器人、相机标定等领域。…

Qt报错QOCI driver not loaded且QOCI available的解决方法

参考 Linux Qt 6安装Oracle QOCI SQL Driver插件&#xff08;适用WSL&#xff09; 安装 QOCI 插件完成后运行 Qt 项目报错&#xff1a; qt.sql.qsqldatabase: QSqlDatabase: QOCI driver not loaded qt.sql.qsqldatabase: QSqlDatabase: available drivers: QMIMER QPSQL QODBC…

【MySQL】 穿透学习数据库理论与知识剖析

前言&#xff1a;本节内容讲述一些数据库的基本概念。 第一个部分就是数据库相关的概念&#xff0c; 比如什么是数据库&#xff0c; 如何理解mysqld以及mysql。第二部分理解数据库和表在系统层面的形式。 第三部分就是mysql的一些操作分类。 第四部分就是数据库的插件配置这些。…

Web Broker(Web服务应用程序)入门教程(1)

1、介绍 Web Broker 组件&#xff08;位于工具面板的“Internet”选项卡中&#xff09;可以帮助您创建与特定统一资源标识符&#xff08;URI&#xff09;相关联的事件处理程序。当处理完成后&#xff0c;您可以通过编程方式构建 HTML 或 XML 文档&#xff0c;并将它们传输给客…

网络安全法详细介绍——爬虫教程

目录 [TOC](目录)一、网络安全法详细介绍1. 网络安全法的主要条款与作用2. 网络安全法与爬虫的关系3. 合法使用爬虫的指南 二、爬虫的详细教程1. 准备环境与安装工具2. 使用requests库发送请求3. 解析HTML内容4. 使用robots.txt规范爬虫行为5. 设置请求间隔6. 数据清洗与存储 三…

25国考照片处理器使用流程图解❗

1、打开“国家公务员局”网站&#xff0c;进入2025公务员专题&#xff0c;找到考生考务入口 2、点击下载地址 3、这几个下载链接都可以 4、下载压缩包 5、解压后先看“使用说明”&#xff0c;再找到“照片处理工具”双击。 6、双击后会进入这样的界面&#xff0c;点击&…

Go 语言之搭建通用 Web 项目开发脚手架

Go 语言之搭建通用 Web 项目开发脚手架 MVC 模式 MVC 模式代表 Model-View-Controller&#xff08;模型-视图-控制器&#xff09; 模式。这种模式用于应用程序的分层开发。 Model&#xff08;模型&#xff09; - 模型代表一个存取数据的对象或 JAVA POJO。它也可以带有逻辑&…

江协科技STM32学习- P34 I2C通信外设

&#x1f680;write in front&#x1f680; &#x1f50e;大家好&#xff0c;我是黄桃罐头&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd;​…

windows在两台机器上测试 MySQL 集群实现实时备份

在两台机器上测试 MySQL 集群实现实时备份的基本步骤&#xff1a; 一、环境准备 机器配置 确保两台机器&#xff08;假设为服务器 A 和服务器 B&#xff09;能够互相通信&#xff0c;例如它们在同一个局域网内&#xff0c;并且开放了 MySQL 通信所需的端口&#xff08;默认是 …

【MIT-OS6.S081笔记1】xv6环境搭建

最近开始做一个操作系统的神课MIT-OS6.S081&#xff0c;我做的是老版本的2020版本的&#xff0c;环境使用的是VirtualBox的Ubuntu系统&#xff0c;在这里记录一下学习的过程。首先需要搭建一下环境&#xff0c;参考官网Tools Used in 6.S081&#xff0c;这个知乎文章也写得很好…

深度学习基础—语言模型和序列生成

引言 深度学习基础—循环神经网络&#xff08;RNN&#xff09;https://blog.csdn.net/sniper_fandc/article/details/143417972?fromshareblogdetail&sharetypeblogdetail&sharerId143417972&sharereferPC&sharesourcesniper_fandc&sharefromfrom_link 上…

kdd比赛方案

解决方案概述 采用两阶段的方法来解决比赛任务。在第一阶段&#xff0c;采用与 SciBERT 集成的跨编码器模型来确定源论文是否是最重要的参考文献之一。在第二阶段&#xff0c;利用了从目标和源论文中得出的特征&#xff0c;以及第一阶段的输出&#xff0c;输入到几个二进制分类…

抖音Ai图文故事号,AI一键生成故事图片变现,涨粉变现超快!

今天分享2个简单好上手&#xff0c;可批量复制&#xff0c;出单超快的Ai项目&#xff0c;那就是AI绘画壁纸号Ai图文故事号。 在抖音、小红书上&#xff0c;壁纸号火的一塌糊涂&#xff0c;新号3天涨粉1500&#xff0c;变现利润超过了4位数 壁纸看起来平平无奇&#xff0c;市场需…

面试题:JVM(三)

1. 面试题 说一说JVM的内存结构是什么样子的,每个区域放什么&#xff0c;各有什么特点&#xff1f;&#xff08;快手、搜狐&#xff09; JVM的内存结构&#xff0c;及各个结构的内容。&#xff08;vivo&#xff09; 详细介绍一下内存结构&#xff08;墨迹天气&#xff09; JVM…

ELK的ElasticStack语法

目录 传送门前言一、索引&#xff08;数据库&#xff09;1、创建索引2、获取索引3、删除索引 二、文档&#xff08;Row行&#xff09;1、创建文档2、获取文档3、修改文档4、删除文档5、高级查询&#xff08;精辟&#xff09;条件查询分页、指定、排序、范围查询全文检索、分组查…

leaflet绘制圆形方案

电子围栏绘制方案: 采用leaflet绘制电子围栏 可以看对应api文档 。原生是英文,所以要重定义,直接覆盖下面的 leaflet.draw-cn.js 文件L.drawLocal = {draw: {toolbar: {// #TODO: this should be reorganized where actions are nested in actions// ex: actions.undo or a…

新能源汽车空调压缩机:科技驱动的冷暖核心

一、新能源汽车空调系统概述 新能源汽车空调系统在车辆中起着至关重要的作用&#xff0c;它直接影响着驾乘人员的舒适度。新能源汽车空调系统主要由制冷系统、加热系统、送风系统、操纵控制系统和空气净化系统等组成。 制冷系统通常由电动压缩机、冷凝器、压力传感器、电子膨…

Javaweb梳理8——数据库设计

Javaweb梳理8——数据库设计 8 数据库设计8.1 数据库设计简介8.2 表关系(一对多)8.3 表关系&#xff08;多对多&#xff09;8.4 表关系&#xff08;一对一&#xff09; 8 数据库设计 8.1 数据库设计简介 软件的研发步骤 数据库设计概念 数据库设计就是根据业务系统的具体需…

IDEA - 快速去除 mapper.xml 黄色警告线和背景色----简化版

1.打开设置 2.去掉黄色警告线设置 3.去掉背景色设置 4.示范图

vue3中使用vue-diff工具来比较数据差异

1.安装vue-diff npm i vue-diff 2.main.js中全局注册 import VueDiff from "vue-diff"; import "vue-diff/dist/index.css";app.use(VueDiff) 3.使用 <template><div class"contain-page"><el-scrollbar height"100vh&…