【Rust】——Trait

🎃个人专栏:

🐬 算法设计与分析:算法设计与分析_IT闫的博客-CSDN博客

🐳Java基础:Java基础_IT闫的博客-CSDN博客

🐋c语言:c语言_IT闫的博客-CSDN博客

🐟MySQL:数据结构_IT闫的博客-CSDN博客

🐠数据结构:​​​​​​数据结构_IT闫的博客-CSDN博客

💎C++:C++_IT闫的博客-CSDN博客

🥽C51单片机:C51单片机(STC89C516)_IT闫的博客-CSDN博客

💻基于HTML5的网页设计及应用:基于HTML5的网页设计及应用_IT闫的博客-CSDN博客​​​​​​

🥏python:python_IT闫的博客-CSDN博客

🐠离散数学:离散数学_IT闫的博客-CSDN博客

​​​​​​🥽Linux:​​​​Linux_Y小夜的博客-CSDN博客

🚝Rust:Rust_Y小夜的博客-CSDN博客

欢迎收看,希望对大家有用!

目录

🎯Trait简介

🎯定义一个Trait

🎯在类型上实现trait

 🎯实现trait的约束

🎯默认实现

🎯trait作为参数

🎯Trait Bound语法

🎯通过+指定多个trait bound

🎯通过where简化trait bound

🎯实现Trait作为返回类型

🎯使用Trait Bound有条件的实现方法


🎯Trait简介

        trait 定义了某个特定类型拥有可能与其他类型共享的功能。可以通过 trait 以一种抽象的方式定义共同行为。可以使用 trait bounds 指定泛型是任何拥有特定行为的类型。

        注意:trait 类似于其他语言中的常被称为 接口(interfaces)的功能,虽然有一些不同。

  •         Trait :抽象的定义共享行为。
  •         Trait bounds(约束):泛型类型参数指定为实现特定行为的参数。
  •         Trait与其他语言的接口(interface)类似,但有些区别。

🎯定义一个Trait

        一个类型的行为由其可供调用的方法构成。如果可以对不同类型调用相同的方法的话,这些类型就可以共享相同的行为了。trait 定义是一种将方法签名组合起来的方法,目的是定义一个实现某些目的所必需的行为的集合。

        展示了一个表现这个概念的公有 Summary trait 的定义:

pub trait Summary {fn summarize(&self) -> String;
}

        在方法签名后跟分号,而不是在大括号中提供其实现。接着每一个实现这个 trait 的类型都需要提供其自定义行为的方法体,编译器也会确保任何实现 Summary trait 的类型都拥有与这个签名的定义完全一致的 summarize 方法。

        trait 体中可以有多个方法:一行一个方法签名且都以分号结尾。

        只有只有方法签名,没有具体实现。

        实现该trait的类型必须提供具体的方法实现。

🎯在类型上实现trait

pub struct NewsArticle {pub headline: String,pub location: String,pub author: String,pub content: String,
}impl Summary for NewsArticle {fn summarize(&self) -> String {format!("{}, by {} ({})", self.headline, self.author, self.location)}
}pub struct Tweet {pub username: String,pub content: String,pub reply: bool,pub retweet: bool,
}impl Summary for Tweet {fn summarize(&self) -> String {format!("{}: {}", self.username, self.content)}
}

        在类型上实现 trait 类似于实现与 trait 无关的方法。区别在于 impl 关键字之后,我们提供需要实现 trait 的名称,接着是 for 和需要实现 trait 的类型的名称。在 impl 块中,使用 trait 定义中的方法签名,不过不再后跟分号,而是需要在大括号中编写函数体来为特定类型实现 trait 方法所拥有的行为。

 🎯实现trait的约束

      现在库在 NewsArticle 和 Tweet 上实现了Summary trait,crate 的用户可以像调用常规方法一样调用 NewsArticle 和 Tweet 实例的 trait 方法了。唯一的区别是 trait 必须和类型一起引入作用域以便使用额外的 trait 方法。这是一个二进制 crate 如何利用 aggregator 库 crate 的例子:

use aggregator::{Summary, Tweet};fn main() {let tweet = Tweet {username: String::from("horse_ebooks"),content: String::from("of course, as you probably already know, people",),reply: false,retweet: false,};println!("1 new tweet: {}", tweet.summarize());
}

        不能为外部类型实现外部 trait。例如,不能在 aggregator crate 中为 Vec<T> 实现 Display trait。这是因为 Display 和 Vec<T> 都定义于标准库中,它们并不位于 aggregator crate 本地作用域中。这个限制是被称为 相干性coherence)的程序属性的一部分,或者更具体的说是 孤儿规则orphan rule),其得名于不存在父类型。这条规则确保了其他人编写的代码不会破坏你代码,反之亦然。没有这条规则的话,两个 crate 可以分别对相同类型实现相同的 trait,而 Rust 将无从得知应该使用哪一个实现。        

🎯默认实现

        有时为 trait 中的某些或全部方法提供默认的行为,而不是在每个类型的每个实现中都定义自己的行为是很有用的。这样当为某个特定类型实现 trait 时,可以选择保留或重载每个方法的默认行为。

pub trait Summary {fn summarize(&self) -> String {String::from("(Read more...)")}
}

        如果想要对 NewsArticle 实例使用这个默认实现,可以通过 impl Summary for NewsArticle {} 指定一个空的 impl 块。

默认实现允许调用相同 trait 中的其他方法,哪怕这些方法没有默认实现。

pub trait Summary {fn summarize_author(&self) -> String;fn summarize(&self) -> String {format!("(Read more from {}...)", self.summarize_author())}
}

为了使用这个版本的 Summary,只需在实现 trait 时定义 summarize_author 即可:

impl Summary for Tweet {fn summarize_author(&self) -> String {format!("@{}", self.username)}
}

注意无法从相同方法的重载实现中调用默认方法。

🎯trait作为参数

pub fn notify(item: &impl Summary) {println!("Breaking news! {}", item.summarize());
}

        对于 item 参数,我们指定了 impl 关键字和 trait 名称,而不是具体的类型。该参数支持任何实现了指定 trait 的类型。适用于简单的情况。

🎯Trait Bound语法

  impl Trait 语法适用于直观的例子,它实际上是一种较长形式我们称为 trait bound语法的语法糖。它看起来像:

pub fn notify<T: Summary>(item: &T) {println!("Breaking news! {}", item.summarize());
}

        这与之前的例子相同,不过稍微冗长了一些。trait bound 与泛型参数声明在一起,位于尖括号中的冒号后面。

  impl Trait 很方便,适用于短小的例子。更长的 trait bound 则适用于更复杂的场景。

pub fn notify(item1: &impl Summary, item2: &impl Summary) {

        这适用于 item1 和 item2 允许是不同类型的情况(只要它们都实现了 Summary)。不过如果你希望强制它们都是相同类型呢?这只有在使用 trait bound 时才有可能:

pub fn notify<T: Summary>(item1: &T, item2: &T) {

🎯通过+指定多个trait bound

        如果 notify 需要显示 item 的格式化形式,同时也要使用 summarize 方法,那么 item 就需要同时实现两个不同的 trait:Display 和 Summary

pub fn notify(item: &(impl Summary + Display)) {

+ 语法也适用于泛型的 trait bound:

pub fn notify<T: Summary + Display>(item: &T) {

🎯通过where简化trait bound

        使用过多的 trait bound 也有缺点。每个泛型有其自己的 trait bound,所以有多个泛型参数的函数在名称和参数列表之间会有很长的 trait bound 信息,这使得函数签名难以阅读。为此,Rust 有另一个在函数签名之后的 where 从句中指定 trait bound 的语法。所以除了这么写:

fn some_function<T: Display + Clone, U: Clone + Debug>(t: &T, u: &U) -> i32 {

还可以像这样使用 where 从句:

fn some_function<T, U>(t: &T, u: &U) -> i32
whereT: Display + Clone,U: Clone + Debug,
{

🎯实现Trait作为返回类型

fn returns_summarizable() -> impl Summary {Tweet {username: String::from("horse_ebooks"),content: String::from("of course, as you probably already know, people",),reply: false,retweet: false,}
}

        返回一个只是指定了需要实现的 trait 的类型的能力在闭包和迭代器场景十分的有用不过。

        这只适用于返回单一类型的情况。

🎯使用Trait Bound有条件的实现方法

        通过使用带有 trait bound 的泛型参数的 impl 块,可以有条件地只为那些实现了特定 trait 的类型实现方法。

use std::fmt::Display;struct Pair<T> {x: T,y: T,
}impl<T> Pair<T> {fn new(x: T, y: T) -> Self {Self { x, y }}
}impl<T: Display + PartialOrd> Pair<T> {fn cmp_display(&self) {if self.x >= self.y {println!("The largest member is x = {}", self.x);} else {println!("The largest member is y = {}", self.y);}}
}

        也可以对任何实现了特定 trait 的类型有条件地实现 trait。对任何满足特定 trait bound 的类型实现 trait 被称为 blanket implementations,它们被广泛的用于 Rust 标准库中。

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

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

相关文章

移动端-2(媒体查询+Less基础+rem适配方案+响应式布局+Bookstrap前端开发构架)

目录 1.rem布局 2.媒体查询 什么是媒体查询 语法规范 mediatype查询类型 关键字 媒体特性 3.Less基础 维护css的弊端 less介绍 less变量 less嵌套 less运算 4.rem适配方案 rem实际开发适配方案1 设计稿常见尺寸宽度 动态设置html标签font-size大小 元素大小取…

网络协议——STP(生成树协议)

1. 什么是环路&#xff1f; 信息经过一系列的转化或传递&#xff0c;然后再返回到起始点&#xff0c;形成一个闭合的循环。 2. 环路的危害 广播风暴&#xff08;广播报文充斥着整个网络&#xff09; MAC地址漂移&#xff0c;从而导致MAC地址表震荡。 使用 display mac…

Rust 基础语法和数据类型

数据类型 Rust提供了一系列的基本数据类型&#xff0c;包括整型&#xff08;如i32、u32&#xff09;、浮点型&#xff08;如f32、f64&#xff09;、布尔类型&#xff08;bool&#xff09;和字符类型&#xff08;char&#xff09;。此外&#xff0c;Rust还提供了原生数组、元组…

医学图像处理 利用pytorch实现的可用于反传的Radon变换和逆变换

医学图像处理 利用pytorch实现的可用于反传的Radon变换和逆变换 前言代码实现思路实验结果 前言 Computed Tomography&#xff08;CT&#xff0c;计算机断层成像&#xff09;技术作为如今医学中重要的辅助诊断手段&#xff0c;也是医学图像研究的重要主题。如今&#xff0c;随…

Mac安装配置Appium

一、安装 nodejs 与 npm 安装方式与 windows 类似 &#xff0c;官网下载对应的 mac 版本的安装包&#xff0c;双击即可安装&#xff0c;无须配置环境变量。官方下载地址&#xff1a;https://nodejs.org/en/download/ 二、安装 appium Appium 分为两个版本&#xff0c;一个是…

yolov9训练自己的数据—vehicle 4类

yolov9训练自己的数据 1 conda环境安装指定版本torch 2 预训练模型测试3 训练自己的数据集3.1 制作数据3.2 创建模型配置文件3.3 创建数据加载配置文件3.4 使用ClearML跟踪训练日志3.5 训练3.6 模型测试3.7 转换成TensorRT模型 4 参考文档 1 conda环境 下载yolov9代码&#xf…

C语言:顺序表专题

目录 一、数据结构之顺序表/链表1.数据结构相关概念1.1什么是数据结构1.2为什么需要数据结构 二、顺序表1.顺序表的概念及结构2.顺序表分类3.动态顺序表的实现 一、数据结构之顺序表/链表 1.数据结构相关概念 1.1什么是数据结构 数据结构是由“数据”和“结构”两词组合而来…

解锁ETLCloud中Kettle的用法

随着大数据时代的到来&#xff0c;数据的处理和管理成为各行各业不可或缺的一环。ETL&#xff08;Extract-Transform-Load&#xff09;工具作为数据处理的重要环节&#xff0c;扮演着将数据从源端抽取出来、经过转换处理&#xff0c;最终加载至目标端的关键角色。在众多ETL工具…

【Python】数据挖掘与机器学习(一)

【Python】数据挖掘与机器学习(一) 大家好 我是寸铁&#x1f44a; 总结了一篇【Python】数据挖掘与机器学习(一)sparkles: 喜欢的小伙伴可以点点关注 &#x1f49d; 【实验1】预测鲍鱼年龄 问题描述 请从一份数据中预测鲍鱼的年龄&#xff0c;数据集在abalone.cvs中&#xff…

【Qt】:常用控件(二:QWidget核心属性)

常用控件&#xff08;二&#xff09; 一.cursor&#xff08;光标形状&#xff09;二.font&#xff08;字体信息&#xff09;三.toolTip&#xff08;提示显示&#xff09;四.focusPolicy&#xff08;焦点&#xff09;五.styleSheet&#xff08;文本样式&#xff09; 一.cursor&a…

Java BigDecimal类

原因 为什么要有BigDecimal类因为二进制的缘故&#xff0c;直接对浮点数进行运算&#xff0c;会导致精度丢失的问题下例&#xff1a;出现了0.1 0.2 <> 0.3 常见的API 这些API中&#xff0c;并不推荐由double类型转换的BigDecimal,因为底层还是double推荐使用由string 类…

QT5-qmediaplayer播放视频及进度条控制实例

qmediaplayer是QT5的播放视频的一个模块。它在很多时候还是要基于第三方的解码器。这里以Ubuntu系统为例&#xff0c;记录其用法及进度条qslider的控制。 首先&#xff0c;制作一个简单的界面文件mainwindow.ui&#xff1a; 然后&#xff0c;下载一个mp4或其他格式视频&#x…

【算法集训】基础算法:二分查找 | 概念篇

二分枚举&#xff0c;也叫二分查找&#xff0c;指的就是给定一个区间&#xff0c;每次选择区间的中点&#xff0c;并且判断区间中点是否满足某个条件&#xff0c;从而选择左区间继续求解还是右区间继续求解&#xff0c;直到区间长度不能再切分为止。 由于每次都是把区间折半&am…

小程序实现订阅功能和测试发送订阅信息

现在一次性订阅是只能用户点一次才能发送一次&#xff0c;而针对长期模板只有规定的几种类目政务、民生、交通等等的才可以&#xff0c;所以说感觉这功能其实已经不是很适合使用了&#xff0c;只适合一些特别的场景才可以使用。 地址&#xff1a;https://developers.weixin.qq…

where 函数

Pandas 中的 where 函数 在 Pandas 中&#xff0c;where 函数用于替换不满足条件的值。具体来说&#xff0c;它返回一个与原始 DataFrame 或 Series 形状相同的新对象&#xff0c;但所有不满足条件的值都被替换为指定的值&#xff08;默认为 NaN&#xff09;。 对于 DataFram…

【Web应用技术基础】JavaScript(7)——案例:点击文字则放大字体

视频已发。截图如下&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</titl…

Java基础知识总结(43)

&#xff08;1&#xff09;初始化块 和构造方法具有相同功能的是初始化块。当创建Java对象时&#xff0c;系统总是先调用类中定义的初始化块 &#xff08;2&#xff09;静态初始化块 如果定义初始化块使用了static修饰&#xff0c;则这个初始化块就变成了静态初始化块&#xf…

html基础介绍

概念 HTML 文件 扩展名是 .html 的文件称为网页文件或者HTML文件HTML 文件使用代码编辑进行编辑&#xff0c;使用浏览器查看效果 声明方式 <!Doctype html>&#xff01;DOCTYPE 是一个文档类型标记&#xff0c;是一种标准通用标记语言的文档类型声明&#xff0c;在 w…

2024.4.6-day11-CSS 背景和精灵图

个人主页&#xff1a;学习前端的小z 个人专栏&#xff1a;HTML5和CSS3悦读 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结&#xff0c;欢迎大家在评论区交流讨论&#xff01; 文章目录 作业2024.4.6学习笔记1 背景2 背景图片3 CSS 精灵图 作业 <!DOCTYPE html&…

项目中 使用 spring cache redis 出现大量keys* 慢查询排查以及修复

前言 业务反馈 redis里有大量的慢查询 而且全是keys 的命令 排查 首先登录 阿里云查看redis的慢查询日志 如下 主要使用到redis cache的注解功能 分别是 CacheEvict 和 Cacheable 注意 CacheEvict 这个比较特殊 会进行驱逐缓存 说白就会删除缓存或者让缓存失效 第一时间想…