当前位置: 首页 > news >正文

rust trait对象

在拥有继承的语言中,可以定义一个名为shape的基类,该类上有一个draw方法。其他的类比如Button、SelectBox继承shape。它们各自覆盖draw方法。调用这些子类的draw方法时,就可以把它们统一当作shape来使用。不过Rust并没有继承,如果想做到这点,就得另寻出路。这个出路就是使用trait对象。trait对象的作用类似基类。

一、定义trait对象

(一)语法格式
trait对象是一种类型,定义语法如下

dyn 约束

约束是trait约束或者生存期约束。可以有多个约束,多个约束之间用+连接。
例如

dyn X
dyn X + Send
dyn X + Send + Sync
dyn X + 'static
dyn X + Send + 'static

X是一个trait

二、使用trait对象

trait对象是动态尺寸类型。像所有的 DST 一样,使用trait对象,必须使用它的指针类型;例如 &dyn SomeTraitBox<dyn SomeTrait>。trait对象的指针包括:
一个指向实现SomeTrait的类型T的实例的指针
一个指向虚拟方法表的指针。虚拟方法表也通常被称为虚函数表,它包含了T实现的SomeTrait的所有方法,T实现的SomeTrait的父trait 的每个方法,还有指向T的实现的指针。

例子

pub trait Draw {fn draw(&self);
}
pub struct Screen {pub shapes: Vec<Box<dyn Draw>>,     //存放trait对象的vector。Box<dyn Draw>就是trait对象,它指向一个实现了Draw的类型的实例
}impl Screen {pub fn run(&self) {for shape in self.shapes.iter() {shape.draw();     //在每个shape上调用draw方法}}
}
pub struct Button {pub width: u32,pub height: u32,pub label: String,
}
impl Draw for Button {fn draw(&self) {// 实际绘制按钮的代码}
}
struct SelectBox {width: u32,height: u32,options: Vec<String>,
}
impl Draw for SelectBox {fn draw(&self) {// code to actually draw a select box}
}
fn main() {let screen = Screen {shapes: vec![Box::new(SelectBox {width: 75,height: 10,options: vec![String::from("Yes"),String::from("Maybe"),String::from("No")],}),Box::new(Button {width: 50,height: 10,label: String::from("OK"),}),],};screen.run();
}

从上面代码中可以看出,是不是与基类指针很类似?

run并不检查元素是Button或者SelectBox的实例。如果实例没有实现trait对象所需的trait则编译错误
例如,

fn main() {let screen = Screen {shapes: vec![Box::new(String::from("Hi")),],};screen.run();
}

这个编译错误,因为String没有实现Draw

三、trait对象与泛型的区别

trait对象与带有trait约束的泛型结构体类似,但是也有不同。泛型参数一次只能替代一个具体类型,而trait对象则允许在运行时替代多种具体类型。
例如

pub struct Screen<T: Draw> {pub shapes: Vec<T>,
}
impl<T> Screen<T>
where T: Draw {pub fn run(&self) {for shape in self.shapes.iter() {shape.draw();}}
}

shapes是一个全是Button类型或者全是SelectBox类型的列表。总之,所有元素类型是相同的。
而使用trait对象,shapes能同时包含Box<Button>Box<SelectBox>,各个元素类型可以不同。

四、trait对象要求对象安全

只有对象安全的trait才可以组成trait对象。如果一个trait中所有的方法有如下属性时,则该trait是对象安全的:
1.返回值类型不为Self
2.方法没有任何泛型参数
Self代表自身。对象安全对于trait对象是必须的,因为一旦有了trait对象,就不再知晓实现该trait的具体类型是什么了。如果trait方法返回具体的Self类型,但是trait对象忘记了其真正的类型,那么方法不可能使用已经忘却的原始具体类型。同理对于泛型类型参数来说,当使用trait时其会放入具体的类型参数:此具体类型变成了实现该trait的类型的一部分。当使用trait对象时其具体类型被抹去了,故无从得知放入泛型参数类型的类型是什么。
一个trait的方法不是对象安全的例子是标准库中的Clone trait。

pub trait Clone {fn clone(&self) -> Self;
}

String实现了Clone trait,当在String实例上调用clone方法时会得到一个String实例。类似的,当调用Vec<T> 实例的clone方法会得到一个Vec<T> 实例。clone的签名需要知道什么类型会代替Self,因为这是它的返回值。
如果尝试做一些违反对象安全规则的事情,编译器会提示你。
例如,

pub struct Screen {pub components: Vec<Box<dyn Clone>>,
}

将会得到如下错误:
error[E0038]: the trait std::clone::Clone cannot be made into an object
Clone不能组成trait对象。

相关文章:

rust trait对象

在拥有继承的语言中&#xff0c;可以定义一个名为shape的基类&#xff0c;该类上有一个draw方法。其他的类比如Button、SelectBox继承shape。它们各自覆盖draw方法。调用这些子类的draw方法时&#xff0c;就可以把它们统一当作shape来使用。不过Rust并没有继承&#xff0c;如果…...

Linux学习第21天:Linux内核定时器驱动开发: 流淌的时间长河

Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 在人类的发展进化中&#xff0c;时间是一个非常重要神秘的物质量。任何事物都是在时间的长河中流淌发生、发展、变化。我们进行驱动开发中对时间的定义和使用也是…...

Centos服务在服务器重启后自启

以Dolphin为例 打开rc.local文件以编辑&#xff1a; sudo vi /etc/rc.d/rc.local在文件中添加您的启动命令。在您的情况下&#xff0c;要添加的命令如下&#xff1a; sh /opt/dolphinscheduler/zookeeper/bin/zkServer.sh start sh /opt/dolphinscheduler/dolphinscheduler/…...

慢性疼痛治疗服务公司Kindly MD申请700万美元纳斯达克IPO上市

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 猛兽财经获悉,慢性疼痛治疗服务公司Kindly MD近期已向美国证券交易委员会&#xff08;SEC&#xff09;提交招股书&#xff0c;申请在纳斯达克IPO上市&#xff0c;股票代码为&#xff08;KDLY&#xff09;,Kindly MD计划通过…...

代码随想录 Day6 哈希 LeetcodeT454 四数之和II T383赎金信 T15 三数之和 T18 四数之和

本文代码思路来源于: 代码随想录 前言 希望大家在刷这部分题的时候先熟悉熟悉哈希结构的基本常用api,比较方便理解. LeetCode T454 四数之和 题目链接:454. 四数相加 II - 力扣&#xff08;LeetCode&#xff09; 题目思路 暴力解法仍然是遍历四个数组解决此题, 哈希的思路有…...

干货速来|教你如何撰写毕业论文

撰写毕业论文对于正常大学毕业至关重要。毕业论文是对学生在大学期间所学知识的综合运用和深入研究的体现&#xff0c;也是对学术能力和独立思考能力的考验。 撰写毕业论文的过程需要学生投入大量的时间和精力&#xff0c;包括选题、文献综述、研究方法选择、数据收集和分析、…...

【ROS 2】-2 话题通信

飞书原文链接&#xff1a; Docs...

Unity之NetCode多人网络游戏联机对战教程(2)--简单实现联机

文章目录 1.添加基本组件2.创建NetworkManager组件3.创建Player4.创建地面5.创建GameManager6.编译运行7. 测试联机后话 1.添加基本组件 NetworkManagerPlayerScene 2.创建NetworkManager组件 创建一个空物体&#xff0c;命名为NetworkManager 选择刚刚创建的NetworkManager…...

makdown文法

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…...

新手程序员怎么接单?

程序员如何在自己年富力强的时候&#xff0c;最大化发挥自己的能力&#xff1f;将超能力转化为“钞能力”&#xff1f; 有人还在苦哈哈当老黄牛&#xff0c;一身使不完的牛劲&#xff0c;有人已经另辟蹊径&#xff0c;开创了自己的一片致富小天地。 接单找兼职&#xff0c;就…...

接口测试——接口协议抓包分析与mock_L2

目录&#xff1a; 抓包工具charles抓包工具fiddler抓包工具证书配置app抓包实战练习接口测试实战练习 1.抓包工具charles 工具介绍 支持 SSL 代理支持流量控制支持重发网络请求&#xff0c;方便后端调试支持修改网络请求参数支持网络请求的截获并动态修改可以自动将 json 或…...

Seata入门系列【1】安装seata 1.7.1+nacos 2.1.1

1 介绍 Seata 是一款开源的分布式事务解决方案&#xff0c;致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式&#xff0c;为用户打造一站式的分布式解决方案。 Github: https://github.com/seata/seata 官方文档&#xff1a;h…...

2023年职业院校技能大赛中职组----大数据应用与服务赛项任务书试题

2023年职业院校技能大赛中职组----大数据应用与服务赛项任务书试题 模块一&#xff1a;数据库系统运维&#xff08;25分&#xff09;任务一&#xff1a;数据库系统搭建&#xff08;10分&#xff09;任务二&#xff1a;房源数据库系统运维&#xff08;15分&#xff09; 模块二&a…...

产品经理的职业前景怎么样?一文为你全面解答!

随着科技的迅速发展和市场竞争的日益激烈&#xff0c;产品经理这个职业变得越来越炙手可热。产品经理负责一款产品的全生命周期管理&#xff0c;从需求收集到设计、开发、测试、发布&#xff0c;再到市场推广和用户反馈&#xff0c;都需要产品经理参与决策。因此&#xff0c;这…...

【深度学习】图像去噪(2)——常见网络学习

【深度学习】图像去噪 是在 【深度学习】计算机视觉 系列文章的基础上&#xff0c;再次针对深度学习&#xff08;尤其是图像去噪方面&#xff09;的基础知识有更深入学习和巩固。 1 DnCNN 1.1 网络结构 1.1.1 残差学习 1.1.2 Batch Normalization (BN) 1.1.2.1 背景和目标…...

八大排序详解

目录 1.排序的概念及应用 1.1 排序的概念 1.2 排序的应用 1.3 常见的排序算法 2.常见排序算法的实现 2.1 直接插入排序 2.1.1 基本思想 2.1.2 动图解析 2.1.3 排序步骤&#xff08;默认升序&#xff09; 2.1.4 代码实现 2.1.5 特性总结 2.2 希尔排序 2.2.1 基本思…...

自定义热加载:如何不停机实现核心代码更新

文章目录 1. 常见的几种实现代码热更新的几种方式对于开发环境我们可以使用部署环境1. 使用 Arthas 的 redefine 命令来加载新的 class 文件2. 利用 URLClassLoader 动态加载3. 通过Java的Instrumentation API 也是可以实现的 2. 实现1. ClassScanner扫描目录和加载类2. 定时任…...

Spring Cloud Alibaba Nacos 2.2.3 (2) - 单机版启动 (winodows 和 linux )

Nacos 2.2.3 (1) - 下载与数据库配置 参考下载与数据库配置 启动服务器 执行 nacos-server-2.2.3\bin 下的startup.sh或者startup.cmd &#xff08;根据不同系统&#xff09; windows 下nacos 单机启动 方式一&#xff1a; 1&#xff0c;打开cmd 2&#xff0c;cd 到nacos-s…...

VB从资源文件中播放wav音乐文件

Private Const SND_SYNC &H0 Private Const SND_MEMORY &H4 API函数 Private Declare Function sndPlaySoundFromMemory Lib "winmm.dll" Alias "sndPlaySoundA" (lpszSoundName As Any, ByVal uFlags As Long) As Long 音乐效果请“单击” Pr…...

web:[HCTF 2018]WarmUp

题目 点进页面&#xff0c;页面只有一张滑稽脸&#xff0c;没有其他的提示信息 查看网页源代码&#xff0c;发现source.php&#xff0c;尝试访问一下 跳转至该页面&#xff0c;页面显示为一段php代码&#xff0c;需要进行代码审计 <?phphighlight_file(__FILE__);class emm…...

CC Switch模型测试功能:构建可靠AI服务的全周期验证方法论

CC Switch模型测试功能&#xff1a;构建可靠AI服务的全周期验证方法论 【免费下载链接】cc-switch A cross-platform desktop All-in-One assistant tool for Claude Code, Codex & Gemini CLI. 项目地址: https://gitcode.com/GitHub_Trending/cc/cc-switch [问题发…...

完整构建流程:从CMake配置到PyPI分发的nanobind项目部署

完整构建流程&#xff1a;从CMake配置到PyPI分发的nanobind项目部署 【免费下载链接】nanobind nanobind: tiny and efficient C/Python bindings 项目地址: https://gitcode.com/gh_mirrors/na/nanobind nanobind是一个用于创建C/Python绑定的轻量级高效工具&#xff0…...

Qwen2.5-VL视觉定位模型效果展示:一句话精准框出图中目标

Qwen2.5-VL视觉定位模型效果展示&#xff1a;一句话精准框出图中目标 1. 视觉定位技术的新突破 想象一下&#xff0c;你正在翻看手机相册寻找一张特定照片——"去年夏天在海边穿红色泳衣的那张"。传统相册需要你一张张翻看&#xff0c;而搭载Qwen2.5-VL视觉定位技术…...

3DS原生GBA游戏体验:open_agb_firm完整使用指南

3DS原生GBA游戏体验&#xff1a;open_agb_firm完整使用指南 【免费下载链接】open_agb_firm open_agb_firm is a bare metal app for running GBA homebrew/games using the 3DS builtin GBA hardware. 项目地址: https://gitcode.com/gh_mirrors/op/open_agb_firm 想要…...

开源TTS新秀Spark-TTS深度评测:零样本克隆与可控生成实战

1. Spark-TTS初探&#xff1a;零样本克隆如何颠覆传统语音合成 第一次接触Spark-TTS时&#xff0c;我正为一个智能客服项目寻找合适的语音合成方案。当时测试了市面上七八种TTS工具&#xff0c;要么需要大量样本训练&#xff0c;要么生成的语音机械感明显。直到发现这个开源项目…...

Monocle2拟时基因富集分析实战:从热图模块到通路解析

1. Monocle2拟时分析基础回顾 如果你正在做单细胞转录组分析&#xff0c;肯定对拟时分析&#xff08;Pseudotime Analysis&#xff09;不陌生。简单来说&#xff0c;这就像给细胞拍"成长视频"&#xff0c;把静态的细胞状态连成动态的发展轨迹。Monocle2作为这个领域的…...

AI 模型推理性能瓶颈与优化方向

AI模型推理性能瓶颈与优化方向 随着AI技术在各行业的广泛应用&#xff0c;模型推理性能成为影响落地效果的关键因素。无论是实时交互场景还是大规模数据处理&#xff0c;推理效率直接决定了用户体验和成本控制。受限于计算资源、算法复杂度及硬件适配性等因素&#xff0c;AI模…...

Gemma-3 Pixel Studio开源镜像:CI/CD自动化测试流水线配置

Gemma-3 Pixel Studio开源镜像&#xff1a;CI/CD自动化测试流水线配置 1. 项目概述 Gemma-3 Pixel Studio是基于Google最新开源的Gemma-3-12b-it多模态大模型构建的高性能对话终端应用。它不仅具备强大的文本理解和生成能力&#xff0c;还集成了卓越的视觉理解功能&#xff0…...

告别‘OSError‘:手把手教你为transformers库设置离线/代理模式,稳定加载预训练模型

构建稳定高效的Hugging Face模型加载环境&#xff1a;从原理到实践 当你在深夜赶项目进度时&#xff0c;突然遇到那个令人窒息的红色报错——"OSError: Couldnt connect to https://huggingface.co"&#xff0c;这感觉就像在马拉松终点线前被绊倒。作为现代NLP开发的…...

PROJECT MOGFACE在复杂网络分析中的应用:图数据建模与推理

PROJECT MOGFACE在复杂网络分析中的应用&#xff1a;图数据建模与推理 最近在分析一个社交网络项目时&#xff0c;我遇到了一个挺头疼的问题&#xff1a;面对几万个用户节点和错综复杂的关注关系&#xff0c;传统的分析方法要么计算量巨大&#xff0c;要么难以挖掘出深层的模式…...