首页 > 其他分享 >Rust的From和Into特征:可能是最常用的转换类特征

Rust的From和Into特征:可能是最常用的转换类特征

时间:2024-02-29 23:25:22浏览次数:32  
标签:转换 String 特征 Into TryFrom 实现 Rust fn

说到FromInto,以及从他们中衍生出的TryFromTryInto,想必大家都不会陌生。它们不像BorrowAsRefToOwned这些默默工作在泛型里的特征,是绝大多数Rust开发者每天都会使用到的东西。今天我们就来加深一下对这四个特征的了解吧~

From和Into

如果说AsRefAsMut的功能是做“引用到引用”的转换的话,那么FromInto做的就是“值到值”的转换了:

pub trait From<T>: Sized {
    // Required method
    fn from(value: T) -> Self;
}

pub trait Into<T>: Sized {
    // Required method
    fn into(self) -> T;
}

纵观两个特征的签名,它们都消耗掉一个值来产生另一个值;这就是FromInto的第一个小特点了:它们会立即把参数消耗掉。

对实现了From<T>的类型U,标准库为T提供了Into<U>的实现;也就是说,在为U实现了From<T>之后,就可以直接使用T::into()来构造U了:

use std::fmt;

struct BeautifulString(String);

impl From<String> for BeautifulString {
    fn from(mut value: String) -> Self {
        value.push_str("(✪ω✪)");
        Self(value)
    }
}

impl fmt::Display for BeautifulString {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

fn main() {
    let string = String::from("I am beautiful!");
    let beautiful: BeautifulString = string.into();	// 看这里
    println!("{}", beautiful); 						// I am beautiful!(✪ω✪)
}

除此以外,From是反身的,也就是说对任何类型T,都有T: From<T>

我们该实现From还是Into?

既然impl From<T> for U之后可以自动获得impl Into<U> for T,那么我们自然应该优先实现From而不是Into了;仅仅当转换的一方不是当前crate的成员时,才应当考虑实现Into。最直观的例子就是我们可以为T实现Into<String>,但肯定不能为String实现From<T>,这违反了Rust的孤儿原则。

使用From和Into的原则

Rust文档中对FromInto的使用提出了以下的几条原则;它们中的一部分在技术角度上并无强制性,但遵循这些原则可以满足一般的用户预期:

  • 转换应当是万无一失的:如果转换可能失败,那么应该使用TryFrom代替,而不是在FromInto的实现中埋下隐患,甚至产生panic。
  • 转换应当是无损的:从语义上来讲,转换过程中不应该丢失或丢弃信息。例如,对i32: From<u16>来说,使用u16: TryFrom<i32>可以将前一个过程的转换结果恢复原始值;但是对u16u32来说,从u32转换为u16便不是无损的,因此也不该实现u16: From<u32>
  • 转换应当是保值的:将i8转换为u8是无损的——被转换为255的-1_i8可以被毫不费力地转换回255,但是我们不能因此就允许u8: From<i8>的存在——毕竟-1和255是截然不同的两个数字,转换过程不保值。又比如说,String: From<u32>是不存在的,因为身为1的数字和身为"1"的文本差别过大;而String: From<char>便是可以接受的,因为'1'"1"都是文本。
  • 转换应当是显而易见的:转换应当是两种类型之间唯一合理的选择。例如,从[u8;4]转换成u32的过程可以有多种选择:使用小字序、大字序和本地字序,所以应当分别为每种字节序实现不同的转换方法,而不是实现u32: From<[u8;4]>

TryFrom和TryInto

TryFromTryInto的功能和上文中介绍过的From/Into相同,但是它们可能会受控地失败:

pub trait TryFrom<T>: Sized {
    type Error;

    // Required method
    fn try_from(value: T) -> Result<Self, Self::Error>;
}

pub trait TryInto<T>: Sized {
    type Error;

    // Required method
    fn try_into(self) -> Result<T, Self::Error>;
}

通用实现

实现U: TryFrom<T>会自动实现T: TryInto<U>TryFrom也是反身的,任何类型T都自动实现了TryFrom<T>

小插曲:T: TryFrom<T>是永远不会失败的,它的返回类型是Result<Self, Infallible>。正如Infallible的名字所言,它用于表示永远不会发生的错误。Infallible将来会被!替代。


这篇文章不算很长,简单地梳理了FromIntoTryFromTryInto四个用于“值到值”的转换的特征。下篇文章将会介绍DisplayToString特征。

标签:转换,String,特征,Into,TryFrom,实现,Rust,fn
From: https://www.cnblogs.com/cinea/p/18045863

相关文章

  • 自注意力和混合特征名词解释
    引言子带变换特征将原始信号分解成不同频带的子信号基本原理是利用一组带通滤波器将信号分割成若干个子频带也可采用离散小波变换,利用小波基函数将信号分解成不同尺度的子信号以便在不同的尺度上分析信号或图像的特性和池化(pooling)同对信号进行降采样可......
  • 特征匹配
    案例1importcv2importnumpyasnpimportmatplotlib.pyplotasplt%matplotlibinlineimg1=cv2.imread('01_Picture/19_Box.png',0)img2=cv2.imread('01_Picture/20_Box_in_scene.png',0)defcv_show(name,img):cv2.imshow(name,img)......
  • Rust 交叉编译 macOS 为 Linux 和 Windows
    目录前言环境案例macOS编译为Linux和Windows可用二进制程序编译为Linux平台编译为Windows平台最后前言鉴于rust中文资料较少,遇到问题的解决方案更少。这里记录遇到的一些问题。Rust支持交叉编译,可以在macOS平台编译出Linux或者Windows可运行的程序,或者在Lin......
  • 抖音技术分享:飞鸽IM桌面端基于Rust语言进行重构的技术选型和实践总结
    本文由ELab团队公众号授权发布,原题《Rust语言在IM客户端的实践》,来自抖音电商前端团队的分享,本文有修订和改动。1、引言本文将介绍飞鸽IM前端团队如何结合Rust对飞鸽客户端接待能力进行的技术提升,一步步从概念验证、路径分解到分工开发,再到最后上线收益论证,并分享了其中遇到的......
  • Python 机器学习 决策树 文本特征的处理
    ​Python机器学习中,决策树是一种常用的分类和回归模型。决策树可以处理数值型特征和类别型特征。对于文本特征,决策树通常使用词袋模型(BOW)或TF-IDF模型进行处理。在处理文本特征时,决策树(和机器学习算法通常)不能直接处理原始文本。文本必须首先转换成算法能理解的数值形式。......
  • rust与python/c++语法区别
    if/matchpubfnanimal_habitat(animal:&str)->&'staticstr{letid=ifanimal=="crab"{//id等于(或拥有)了一个匿名函数的返回值1}elseifanimal=="gopher"{2}elseifanimal=="snake"......
  • 【rust】《 Rust安装并配置cargo国内源(提供rust编译器) 》
    下载Rust安装程序官网地址:https://www.rust-lang.org/tools/installWindow直接点击DownloadRustup-init.exe就可以下载运行程序。运行安装程序双击下载的rustup-init.exe程序,此时会弹出命令窗口命令窗口内输入1  ;1表示默认形式安装,Rust的环境变量会自动添加到系统......
  • CF1209G2 Into Blocks (hard version) 题解
    Description给你\(n\),\(q\),\(n\)表示序列长度,\(q\)表示操作次数。我们需要达成这么一个目标状态:如果存在\(x\)这个元素,那么必须满足所有\(x\)元素都必须在序列中连续。然后你可以进行这么一种操作,将所有的\(x\)元素的变为任意你指定的\(y\)元素,并且花费\(cnt[x......
  • Rust的Cow类型有什么用?详解Cow及其用途
    Rust的智能指针有哪些?大多数人都能马上答出Box<T>、Rc<T>和Arc<T>、Ref<T>和在异步编程中很常见的Pin<P>等等。不过,有一个可能经常被大多数人遗忘的类型,它功能强大,利用好了可以节省很多复制开销;它就是这篇文章的主角:Cow<B>。什么是COW(Copy-On-Write)?在开始之前,有必要先介绍一下CO......
  • Rust的ToOwned特征:泛型版的Clone
    std::borrow::ToOwned是Rust标准库中的一个特征,用于从借用的数据中创建一个具有所有权的副本。它的作用和Clone是一样的,但是相比Clone,它支持泛型;也就是说我们可以将一个类型T“Clone”为另一个类型U。这对处理一些特殊的类型来说很有用。ToOwned的签名ToOwned提供了两个方法,其中......