跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
搜索
|注册
博客列表
Rust

Rust trait 对象执行动态分发

综述由AI生成Rust 中的 trait 对象支持动态分发,允许在运行时确定调用的方法,但需权衡内联优化。对象安全的 trait 限制了返回值不能为 Self 且不能有泛型参数。标准库的 Clone trait 因返回 Self 类型而无法作为 trait 对象使用,编译时会报错 E0038。

草莓泡芙发布于 2024/3/9更新于 2026/5/37 浏览
Rust trait 对象执行动态分发

Rust trait 对象与动态分发

静态分发与动态分发

回顾第十章'泛型代码的性能'中讨论的内容,当对泛型使用 trait bound 时,编译器会进行单态化处理:为每一个被泛型类型参数代替的具体类型生成非泛型的函数和方法实现。单态化所产生的代码进行静态分发(static dispatch)。静态分发发生于编译器在编译时就知晓调用了什么方法的时候。

这与动态分发(dynamic dispatch)相对,这时编译器在编译时无法知晓调用了什么方法。在动态分发的情况下,编译器会生成在运行时确定调用了什么方法的代码。

当使用 trait 对象时,Rust 必须使用动态分发。编译器无法知晓所有可能用于 trait 对象代码的类型,所以它也不知道应该调用哪个类型的哪个方法实现。为此,Rust 在运行时使用 trait 对象中的指针来知晓需要调用哪个方法。动态分发也阻止编译器有选择地内联方法代码,这会相应地禁用一些优化。尽管在编写示例支持代码的过程中确实获得了额外的灵活性,但仍然需要权衡取舍。

Trait 对象需要类型安全

只有对象安全(object-safe)的 trait 才能实现为特征对象。这里有一些复杂的规则来实现 trait 的对象安全,但在实践中,只有两个相关的规则。如果一个 trait 中定义的所有方法都符合以下规则,则该 trait 是对象安全的:

  • 返回值不是 Self
  • 没有泛型类型的参数

Self 关键字是我们在 trait 与方法上的实现的别称,trait 对象必须是对象安全的,因为一旦使用 trait 对象,Rust 将不再知晓该实现的返回类型。如果一个 trait 的方法返回了一个 Self 类型,但是该 trait 对象忘记了 Self 的确切类型,那么该方法将不能使用原本的类型。当 trait 使用具体类型填充的泛型类型时也一样:具体类型成为实现 trait 的对象的一部分,当使用 trait 对象却忘了类型是什么时,无法知道应该用什么类型来填充泛型类型。

Clone trait 示例

一个非对象安全的 trait 例子是标准库中的 Clone trait。Clone trait 中的 clone 方法的声明如下:

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

String 类型实现了 Clone trait,当我们在 String 的实例对象上调用 clone 方法时,我们会得到一个 String 类型实例对象。相似地,如果我们调用 Vec 实例对象上的 clone 方法,我们会得到一个 Vec 类型的实例对象。clone 方法的标签需要知道哪个类型是 Self 类型,因为 Self 是它的返回类型。

当我们尝试编译一些违反 trait 对象的对象安全规则的代码时,我们会收到编译器的提示。例如,我们想实现 Screen 结构体来保存一个实现了 Clone trait 而不是 Draw trait 的类型,如下所示:

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

我们将会收到如下错误:

Compiling gui v0.1.0 (file:///projects/gui)
error[E0038]: the trait `Clone` cannot be made into an object
 --> src/lib.rs:2:29
  |
2 | pub components: Vec<Box<dyn Clone>>,
  |                             ^^^^^^ `Clone` cannot be made into an object
  |
  = note: the trait cannot be made into an object because it requires `Self: Sized`
  = note: for a trait to be 'object safe' it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit https://doc.rust-lang.org/nightly/std/marker/trait.ObjectSafe.html

这个错误意味着我们不能将此 trait 用于 trait 对象。

目录

  1. Rust trait 对象与动态分发
  2. 静态分发与动态分发
  3. Trait 对象需要类型安全
  4. Clone trait 示例
  • 💰 8折买阿里云服务器限时8折了解详情
  • GPT-5.5 超高智商模型1元抵1刀ChatGPT中转购买
  • 代充Chatgpt Plus/pro 帐号了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 基于 SRS 与 WebRTC 的 RTSP 多路摄像头低延迟监控方案
  • 数据结构入门:顺序表的实现与原理
  • C++ STL 容器:基于红黑树模拟实现 map 与 set
  • Virt-A-Mate (VAM) v1.22 虚拟实境软件介绍
  • 灵感画廊 AI 绘画环境配置指南
  • K8S 环境下 Zabbix 监控平台部署实践
  • 开源 RAG 引擎 RAGFlow 部署与实战指南
  • PyTorch CycleGAN 详解与实现
  • 基于 FPGA 的简易数据采集系统设计
  • Java JDK 下载安装与环境配置详细教程
  • C++ unordered_set 与 unordered_map 核心解析
  • Flutter 集成 google_generative_language_api 适配鸿蒙实现 AI
  • 电力巡检机器人主流厂商解析与技术发展趋势
  • Stable Diffusion:AI 图像生成技术原理与应用
  • 大模型推理框架选型入门:Ollama、llama.cpp 与 vLLM 对比
  • Bidili SDXL Generator 快速部署与使用指南
  • 动态规划专题:子序列问题核心模型与实现
  • Faster-Whisper 本地实时语音转文本部署指南
  • 手把手教你打造本地私有化AI知识库:Obsidian + OpenCode + Agent Client + MCP Server 完全指南
  • CVPR 2024 论文解读:Fusion-Mamba 跨模态目标检测

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online