资讯动态

Rust 方法语法(Method Syntax)完全指南:基于《The Rust Programming Language》的结构体方法实战解析

发布时间:2026/10/5 6:49:58 来源:尧图企业网站定制
教程文档【免费下载链接】bookThe Rust Programming Language项目地址https://gitcode.com/gh_mirrors/bo/book点击查看免费下载方法Method是 Rust 中面向数据组织行为的第一工具它与函数一样用fn声明、可以有参数和返回值但被定义在结构体以及枚举、trait 对象的上下文之内且第一个参数永远是self——即被调用方法的结构体实例本身。本文基于本仓库《The Rust Programming Language》即著名的the book当前版本 方法语法章节 展开并结合仓库中配套的 listings 示例代码 逐个讲解impl块、self/mut self/self三种接收者、自动引用与解引用、关联函数与多impl块等核心概念。读完本文你将能够熟练地把领域类型上的数据与行为组织进impl块写出符合 Rust 所有权哲学、可读性与封装性兼备的代码。说明本仓库同时保留了三套文档——redirects/旧版链接的重定向页、first-edition/第一版与src/当前版本。本文以当前版本 ch05-03 方法语法 为骨架redirects/method-syntax.md正是旧链接指向该章节的入口其中开篇给出的impl Rectangle { fn area(self) - u32 { ... } }示例也正是我们下面要剖析的第一个例子。从函数到方法把行为放进类型在 Rust 中函数function与方法method的根本区别在于定义位置与第一个参数函数独立存在与具体类型无关方法定义在结构体或枚举、trait 对象分别见 枚举章节 与 trait 对象章节的上下文内第一个参数必须是self代表方法被调用时所在的那个结构体实例。把Rectangle的面积计算从独立函数改写为方法是理解这一转变的经典例子。仓库中 listing-05-13 源码 展示了完整代码#[derive(Debug)] struct Rectangle { width: u32, height: u32, } impl Rectangle { fn area(self) - u32 { self.width * self.height } } fn main() { let rect1 Rectangle { width: 30, height: 50, }; println!( The area of the rectangle is {} square pixels., rect1.area() ); }这里的关键动作有两个开启implimplementation块impl Rectangle { ... }意味着大括号内的一切都与Rectangle类型关联。把area函数移入impl块并把第一个参数从rectangle: Rectangle改为self。在main中原先把rect1作为参数传给area函数的写法变成了在rect1实例上调用.area()方法的方法语法实例后跟一个点号、方法名、括号及参数。调用方式的变化看似微小却带来了组织性上的质变——类型的行为不再散落在库的各处函数里而是集中在该类型自己的impl块中未来使用者无需四处搜寻某个类型能做什么。self的本质self: Self与Self别名在area方法签名里self并非特殊语法它其实是self: Self的简写。在impl块内部类型名Self是这个impl块所服务的类型的别名此处即Rectangle。Rust 要求方法第一个参数必须是名为self、类型为Self的参数因此允许你用self一个名字来缩写整个self: Self。注意缩写self时借用的并不会自动补上——你需要显式写出self来表明这个方法借用Self实例这与之前函数版签名里的rectangle: Rectangle是同一回事。我们之所以选择self与函数版选择Rectangle的理由完全一致不想取得实例的所有权只想读取结构体中的数据不打算修改。由此引出了 Rust 方法接收者的三种形态它们直接映射到所有权与借用规则接收者写法语义典型用途self不可变借用实例只读访问数据调用后实例仍可继续使用mut self可变借用实例方法内部需要修改该实例的字段或状态self取得实例所有权方法把self变换成其他东西且希望调用者之后无法再使用原实例第三种形态self在实际代码中比较少见通常用于把self转换为别的类型的场景例如消耗一个String并返回其中的字节内容。这与本书 所有权章节 讲解的移动move语义一脉相承一旦self被移动进方法调用方原有的实例便随之失效。方法与字段同名getter 与无歧义的点号访问Rust 允许方法使用与结构体字段相同的名字。仓库中 no-listing-06-method-field-interaction 源码 给出了一个名为width的方法impl Rectangle { fn width(self) - bool { self.width 0 } } fn main() { let rect1 Rectangle { width: 30, height: 50, }; if rect1.width() { println!(The rectangle has a nonzero width; it is {}, rect1.width); } }这段代码演示了 Rust 如何消解歧义rect1.width()带括号 → Rust 知道你要调用方法widthrect1.width不带括号 → Rust 知道你要访问字段width。同名的字段与方法可以共存各司其职。当方法只负责返回字段值而不做其他事情时它被称为getter。与某些语言不同Rust 不会为结构体字段自动生成 getter。getter 的价值在于封装你可以把字段设为私有private把方法设为公开public从而将只读访问作为类型公共 API 的一部分暴露出去。关于pub与私有/公开的完整讨论见 模块章节。为什么没有-运算符自动引用与解引用在 C/C 中调用方法需要两个不同的运算符对象直接调用用.通过指针调用必须先解引用用-等价于(*object).something()。Rust 则没有-运算符取而代之的是自动引用与解引用automatic referencing and dereferencing——方法调用是 Rust 中少数具备这一行为的场景。当你写object.something()时Rust 会自动在object上补上、mut或*使其与方法签名的接收者匹配。因此下面两种写法完全等价p1.distance(p2); (p1).distance(p2);第一种写法显然清爽得多。这一机制之所以可靠是因为方法拥有清晰的接收者——self的类型。给定接收者与方法名Rust 就能确定该方法是只读self、可变mut self还是消费型self。让借用对方法接收者隐式化是 Rust 所有权在实践中保持人体工学ergonomic的重要一环你无需手动写出一大串mut、*等引用符号编译器会替你处理。带更多参数的方法can_hold实战方法当然可以有多个参数且除self外的参数与函数参数毫无区别。以判断一个矩形能否完全容纳另一个矩形为例仓库 listing-05-14 源码 展示了调用端期望的形态fn main() { let rect1 Rectangle { width: 30, height: 50, }; let rect2 Rectangle { width: 10, height: 40, }; let rect3 Rectangle { width: 60, height: 45, }; println!(Can rect1 hold rect2? {}, rect1.can_hold(rect2)); println!(Can rect1 hold rect3? {}, rect1.can_hold(rect3)); }期望输出为Can rect1 hold rect2? true Can rect1 hold rect3? falserect2的两条边都小于rect1而rect3比rect1更宽。从调用代码rect1.can_hold(rect2)可以反推参数类型传入的是rect2即对Rectangle实例的不可变借用。我们只需要读取rect2的数据无需写入否则应传可变借用并且希望main在调用can_hold后仍能继续使用rect2因此不可变借用正合适。对应实现见 listing-05-15 源码impl Rectangle { fn area(self) - u32 { self.width * self.height } fn can_hold(self, other: Rectangle) - bool { self.width other.width self.height other.height } }方法参数与函数参数的行为完全一致多个参数依序写在self之后即可。这里can_hold依次比较self与other的宽、高只有两者都更大时才返回true。关联函数Associated FunctionsSelf构造器与::语法impl块中定义的所有函数统称关联函数associated functions因为它们都与impl后的那个类型相关联。其中一类特殊的关联函数不以self作为第一个参数因此不是方法因为它们不需要类型实例即可工作。你早已用过这样的函数String::from就是定义在String类型上的关联函数。不以self为第一参数的关联函数常被用作构造函数返回该结构体的一个新实例。这类函数习惯上命名为new但需要注意new并不是语言内置的特殊名称它只是一个约定俗成的名字。例如仓库 no-listing-03-associated-functions 源码 定义了一个square关联函数用一个维度同时充当宽和高免去重复指定两次的麻烦impl Rectangle { fn square(size: u32) - Self { Self { width: size, height: size, } } } fn main() { let sq Rectangle::square(3); }这里的Self在返回类型和函数体中同样是impl Rectangle中Rectangle的别名因此Self { ... }即构造一个Rectangle实例。调用关联函数使用::语法并冠以结构体名let sq Rectangle::square(3);。::由结构体作命名空间它同时用于关联函数与模块产生的命名空间模块详见 模块章节。多个impl块语法合法与真正价值每个结构体允许拥有多个impl块。例如 listing-05-15 的代码与 listing-05-16 源码 中把每个方法拆进独立impl块的写法完全等价impl Rectangle { fn area(self) - u32 { self.width * self.height } } impl Rectangle { fn can_hold(self, other: Rectangle) - bool { self.width other.width self.height other.height } }对于当前这个简单例子拆分多个impl块并无必要但它是合法语法。其真正价值将在第 10 章讲解泛型与 trait时显现多impl块允许你按 trait 分组实现逻辑、按泛型约束分别提供不同的实现让代码组织更清晰。在本书中对应 泛型章节 与 trait 章节。与仓库的对应关系文档与可编译示例如何同步本仓库的文档工程采用 mdBook 的rustdoc_include机制正文如 ch05-03-method-syntax.md中的代码块并不是手工复制的文本而是通过{{#rustdoc_include ../listings/...}}指令直接嵌入listings/目录下真实可编译的 Cargo 项目。这意味着书中出现的每一段代码都来自经过验证的源码文件读者可以进入对应目录例如listings/ch05-using-structs-to-structure-related-data/listing-05-13/直接运行cargo run复现本文所有输出。这也是本文所有示例均以 listings 目录 为唯一事实来源的原因——你看到的每一行代码都与仓库中可运行的示例一一对应。总结方法语法的核心脉络可以归结为三点impl块把行为与类型绑定结构体及枚举、trait 对象上的所有能力集中在impl块内方法则是第一个参数固定为self的关联函数self的三种形态承载所有权语义self只读、mut self可写、self消费配合自动引用/解引用机制让方法调用既安全又简洁关联函数与多impl块补齐组织能力Rectangle::square这类构造器用::调用多个impl块则为后续泛型与 trait 编程铺路。结构体让你为领域创建有意义的自定义类型impl块则让你把这些类型能做什么完整、集中、可检索地表达出来。在此基础上本书下一站是 枚举enum——另一种自定义类型的方式它将在模式匹配与状态建模中与结构体互为补充。赞分享教程文档【免费下载链接】bookThe Rust Programming Language项目地址https://gitcode.com/gh_mirrors/bo/book点击查看免费下载相关推荐Webpack开发服务器与html-webpack-template热重载最佳实践Webpack开发服务器与html webpack template热重载最佳实践 html webpack template是一个功能丰富的Webpack模板Rust 编程语言The Rust Programming Language用结构体 Struct 组织相关联的数据Rust 编程语言The Rust Programming Language用结构体 Struct 组织相关联的数据 结构体struct是 Rust教程文档The Algorithms - Rust 算法库全景指南用 Rust 实现全部算法与数据结构The Algorithms Rust 算法库全景指南用 Rust 实现全部算法与数据结构 本篇技术指南围绕 The Algorithms Rust 开源项目示例工程上一篇一条命令免费把手机声音投到电脑Android 音频转发工具 sndcpy下一篇免费开源鼠标连点器 MouseClick 快速指南三步安装五分钟跑通自动点击创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑