Trait与生命周期

原文链接:(*´∇`*) 咦,又好了~ Rust – xiaocr_blogicon-default.png?t=N7T8http://www.xiaocr.fun/index.php/2024/03/18/trait%E4%B8%8E%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F/

目录

Trait

定义trait

默认实现

trait作为参数

Trait Bound语法

通过+指定多个 trait bound

通过where简化 trait bound

返回实现了 trait 的类型

生命周期

生命周期避免了悬垂引用

函数中泛型生命周期

生命周期标记语法

函数签名中的生命周期标注

结构体定义中生命周期标注

生命周期省略

静态生命周期

结合泛型类型参数、trait bounds 和生命周期


😃Trait

trait 告诉 Rust 编译器某个特定类型拥有可能与其他类型共享的功能。可以通过 trait 以一种抽象的方式定义共享的行为


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

❗️定义trait

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

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

这里使用 trait 关键字来声明一个 trait,后面是 trait 的名字,在这个例子中是 Summary。在大括号中声明描述实现这个 trait 的类型所需要的行为的方法签名,在这个例子中是 fn summarize(&self) -> String。

默认实现


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

trait作为参数

使用 trait 来接受多种不同类型的参数

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

对于 item 参数,我们指定了 impl 关键字和 trait 名称,而不是具体的类型。该参数支持任何实现了指定 trait 的类型。在 notify 函数体中,可以调用任何来自 Summary trait 的方法,比如 summarize。我们可以传递任何 NewsArticle 或 Tweet 的实例来调用 notify。任何用其它如 String 或 i32 的类型调用该函数的代码都不能编译,因为它们没有实现 Summary。

Trait Bound语法

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

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

通过+指定多个 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) {

通过指定这两个 trait bound,notify 的函数体可以调用 summarize 并使用 {} 来格式化 item。

通过where简化 trait bound

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

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

返回实现了 trait 的类型

也可以在返回值中使用 impl Trait 语法,来返回实现了某个 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,}
}

生命周期

生命周期的概念从某种程度上说不同于其他语言中类似的工具,毫无疑问这是 Rust 最与众不同的功能。

生命周期避免了悬垂引用

生命周期的主要目标是避免悬垂引用,它会导致程序引用了非预期引用的数据

{let r;{let x = 5;r = &x;}println!("r: {}", r);
}

会出现错误,:“x dose not live long enough

函数中泛型生命周期

下面这个代码是会报错的

fn main() {let string1 = String::from("abcd");let string2 = "xyz";let result = longest(string1.as_str(), string2);println!("The longest string is {}", result);
}
fn longest(x: &str, y: &str) -> &str {if x.len() > y.len() {x} else {y}
}

因为 Rust 并不知道将要返回的引用是指向 x 或 y。事实上我们也不知道,因为函数体中 if 块返回一个 x 的引用而 else 块返回一个 y 的引用!

当我们定义这个函数的时候,并不知道传递给函数的具体值,所以也不知道到底是 if 还是 else 会被执行。我们也不知道传入的引用的具体生命周期

77c47f15aef222b134cb6484a0a7a6b9.png

生命周期标记语法

生命周期标注并不改变任何引用的生命周期的长短。与当函数签名中指定了泛型类型参数后就可以接受任何类型一样,当指定了泛型生命周期后函数也能接受任何生命周期的引用。生命周期标注描述了多个引用生命周期相互的关系,而不影响其生命周期。

&i32        // 引用
&'a i32     // 带有显式生命周期的引用
&'a mut i32 // 带有显式生命周期的可变引用

函数签名中的生命周期标注

就像泛型类型参数,泛型生命周期参数需要声明在函数名和参数列表间的尖括号中

fn longest <'a>(x: &'a str, y: &'a str) -> &'a str {if x.len() > y.len() {x} else {y}
}

结构体定义中生命周期标注

需要为结构体定义中的每一个引用添加生命周期标注

struct ImportantExcerpt<'a> {part: &'a str,
}fn main() {let novel = String::from("Call me Ishmael. Some years ago...");let first_sentence = novel.split('.').next().expect("Could not find a '.'");let i = ImportantExcerpt { part: first_sentence };
}

生命周期省略

在编写了很多 Rust 代码后,Rust 团队发现在特定情况下 Rust 开发者们总是重复地编写一模一样的生命周期标注。这些场景是可预测的并且遵循几个明确的模式。生命周期省略规则lifetime elision rules)

  • 第一条规则是每一个是引用的参数都有它自己的生命周期参数。换句话说就是,有一个引用参数的函数有一个生命周期参数:fn foo<'a>(x: &'a i32),有两个引用参数的函数有两个不同的生命周期参数,fn foo<'a, 'b>(x: &'a i32, y: &'b i32),依此类推。
  • 第二条规则是如果只有一个输入生命周期参数,那么它被赋予所有输出生命周期参数:fn foo<'a>(x: &'a i32) -> &'a i32。
  • 第三条规则是如果方法有多个输入生命周期参数并且其中一个参数是 &self 或 &mut self,说明是个对象的方法(method)

静态生命周期

'static,其生命周期能够存活于整个程序期间。所有的字符串字面量都拥有 'static 生命周期

fn main() {
let s: &'static str = "I have a static lifetime.";
}

结合泛型类型参数、trait bounds 和生命周期

fn main() {
use std::fmt::Display;fn longest_with_an_announcement<'a, T>(x: &'a str, y: &'a str, ann: T) -> &'a strwhere T: Display
{println!("Announcement! {}", ann);if x.len() > y.len() {x} else {y}
}
}

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

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

相关文章

opengl日记12-opengl坐标系统

文章目录 环境代码CMakeLists.txtvertexShaderSource.vsmain.cpp 总结 环境 系统&#xff1a;ubuntu20.04opengl版本&#xff1a;4.6glfw版本&#xff1a;3.3glad版本&#xff1a;4.6cmake版本&#xff1a;3.16.3gcc版本&#xff1a;10.3.0 在<opengl学习日记11-opengl的t…

2024年旅游卡代理好做嘛?浅析旅游卡加盟项目的发展前景

旅游卡代理作为一种新型的旅游消费方式&#xff0c;近年来备受瞩目。其中&#xff0c;千益畅行共享旅游卡作为旅游卡代理市场的一员&#xff0c;其便捷性和实用性得到了广大消费者的认可。那么&#xff0c;旅游卡代理究竟好做吗&#xff1f;千益畅行共享旅游卡的发展前景又如何…

【Caddy】 Ubuntu 下卸载 Caddy

要在 Ubuntu 下卸载 Caddy&#xff0c;你可以按照以下步骤进行&#xff1a; 步骤一&#xff1a;停止 Caddy 服务 首先&#xff0c;停止正在运行的 Caddy 服务&#xff1a; sudo systemctl stop caddy步骤二&#xff1a;卸载 Caddy 软件包 执行以下命令卸载 Caddy 软件包&am…

【算法】差分、前缀和(重新排序)

给定一个数组 A和一些查询 Li,Ri&#xff0c;求数组中第 Li 至第 Ri个元素之和。 小蓝觉得这个问题很无聊&#xff0c;于是他想重新排列一下数组&#xff0c;使得最终每个查询结果的和尽可能地大。 小蓝想知道相比原数组&#xff0c;所有查询结果的总和最多可以增加多少? 输…

Java 什么时候类会被加载?

Java 什么时候类会被加载&#xff1f; 题目 Java 什么时候类会被加载&#xff1f; 推荐解析 1&#xff09;创建类的实例&#xff0c;也就是 new 一个对象 public class Test {public static void main(String[] args) {MyClass obj new MyClass(); // 通过new关键字实例化…

多语言LLM的状态:超越英语

多语言大语言模型的发展现状&#xff1a;超越英语 引言 据微软研究院的数据显示&#xff0c;世界上大约88%的语言&#xff0c;即12亿人的母语&#xff0c;缺乏对大型语言模型&#xff08;LLM&#xff09;的访问。这是因为大多数LLM都是以英语为中心的&#xff0c;即它们大多是…

Java:接口

目录 1.接口的概念2.接口的语法规则3.接口使用4.接口的特性5.实现多个接口6.接口中的继承7.抽象类和接口的区别 1.接口的概念 在现实生活中&#xff0c;接口的例子比比皆是&#xff0c;比如&#xff1a;笔记本上的USB口&#xff0c;电源插座等。 电脑的USB口上&#xff0c;可以…

pycorrector检测OCR错字实践

参考&#xff1a;https://github.com/shibing624/pycorrector/tree/master/examples/macbert stopwords.txt 添加专业停用词&#xff0c;避免错误 设置自定义词典&#xff0c;避免将正确的词错误检测成错误的词 from pycorrector import Corrector m Corrector() m.set_cus…

Windows系统部署GoLand结合内网穿透实现SSH远程Linux服务器开发调试

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法|MySQL| ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-HIOuHATnug3qMHzx {font-family:"trebuchet ms",verdana,arial,sans-serif;f…

系统学习Python——装饰器:“私有“和“公有“属性案例-[为Python3.X重定义运算符重载方法的途径:内联定义]

分类目录&#xff1a;《系统学习Python》总目录 正如前面的文章所提到的&#xff0c;Python3.X中最直接的解决方案是&#xff1a;在像装饰器这样的基于委托的类中&#xff0c;重新定义可能在内嵌对象中出现的运算符重载名称。这种方法并不理想&#xff0c;因为它产生了一些代码…

把软件加入开机自启动

注意这个方法最佳效果是适用于打开软件后,关闭窗口不会停止服务 例如 nginx 1.把nginx的快捷方式放到如图所示的文件夹下 C:\Users\KIA_27\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup 注意KIA_27应改为你自己的用户名

一维前缀和一维差分(下篇讲解二维前缀和二维差分)(超详细,python版,其他语言也很轻松能看懂)

本篇博客讲解一维前缀和&#xff0c;一维差分&#xff0c;还会给出一维差分的模板题&#xff0c;下篇博客讲解 二维前缀和&二维差分。 一维前缀和&#xff1a; 接触过算法的小伙伴应该都了解前缀和&#xff0c;前缀和在算法中应用很广&#xff0c;不了解也没有关系&#…

24计算机考研调剂 | (研究所)北京微电子技术研究所

北京微电子技术研究所2024年考研调剂信息 调剂信息 一、招生专业 二、调剂对象 统考科目为思想政治理论、英语&#xff08;一&#xff09;、数学&#xff08;一&#xff09;&#xff1b;本科为电子科学与技术、微电子学、集成电路设计、电子信息工程、通信工程、计算机科学与…

Java Day13 多线程

多线程 1、 方式一 Thread2、实现Runnable接口3、实现 Callable接口4、与线程有关的操作方法5、线程安全问题5.1 取钱案例5.2 线程同步5.2.1 同步代码块5.2.2 同步方法5.2.3 Lock锁 6、线程池6.2 创建线程池6.2.1 使用ExecutorService创建新任务策略6.2.2 使用Executors工具类创…

3.21小题总结

第一题&#xff1a;生日蛋糕 题解&#xff1a;这题是蛋糕结构是一层一层的&#xff0c;估计很多人很快就能想到是dfs&#xff0c;但是这题的难想的点在于 你每层的状态该怎么去确定&#xff0c;你怎么来确定每层的半径和高度是多少&#xff0c;一开始我也不知很理解&#xff0…

82.删除排序链表中的重复元素II

给定一个已排序的链表的头 head &#xff0c; 删除原始链表中所有重复数字的节点&#xff0c;只留下不同的数字 。返回 已排序的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,3,4,4,5] 输出&#xff1a;[1,2,5]示例 2&#xff1a; 输入&#xff1a;head [1,1,1,2…

贝尔曼方程【Bellman Equation】

强化学习笔记 主要基于b站西湖大学赵世钰老师的【强化学习的数学原理】课程&#xff0c;个人觉得赵老师的课件深入浅出&#xff0c;很适合入门. 第一章 强化学习基本概念 第二章 贝尔曼方程 文章目录 强化学习笔记一、状态值函数贝尔曼方程二、贝尔曼方程的向量形式三、动作值…

刷题28-30(力扣0322/0078/0221)

0322. 零钱兑换 题目&#xff1a; 给你一个整数数组 coins &#xff0c;表示不同面额的硬币&#xff1b;以及一个整数 amount &#xff0c;表示总金额。计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额&#xff0c;返回 -1 。你可以…

【微服务】Nacos配置管理

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;微服务 ⛺️稳中求进&#xff0c;晒太阳 Nacos除了可以做注册中心&#xff0c;同样可以做配置管理来使用。 1.统一配置管理 当微服务部署的实例越来越多&#xff0c;达到数十、数百时&am…

【C语言】对称密码——栅栏的加密和解密

栅栏密码的原理&#xff1a; 栅栏层数n ①把将要传递的信息中的字母交替排成上下n行。 ②再将下面每一行字母排依次在上面一行的后边&#xff0c;从而形成一段密码。 ③例如&#xff1a;栅栏层数为2 明文&#xff1a;THE LONGEST DAY MUST HAVE AN END 加密&#xff1a; …