Sway 函数、方法与关联函数完全指南:声明、调用与返回值详解
2026/9/12 17:40:15 网站建设 项目流程

Sway 函数、方法与关联函数完全指南:声明、调用与返回值详解

【免费下载链接】sway🌴 Empowering everyone to build reliable and efficient smart contracts.项目地址: https://gitcode.com/GitHub_Trending/sw/sway

Sway 是 Fuel 生态中用于编写智能合约的领域特定语言,函数是组织代码、实现复用最核心的语法单元。本指南基于当前仓库sway项目中 functions 文档 及其配套示例代码,系统讲解函数(function)、方法(method)与关联函数(associated function)的声明方式、调用语法、返回值规则与构造器模式,帮助你写出结构清晰、可复用的 Sway 智能合约代码。阅读完成后,你将掌握fn关键字的完整用法、self参数与impl块的组织方式,以及显式与隐式两种返回机制的区别。

三种代码组织方式:函数、方法与关联函数

在 Sway 中,函数、方法和关联函数本质上都用于"把一段功能打包起来,以便在多个地方复用而无需重复书写"。它们的区别在于是否与某个具体对象(类型实例)绑定

名称定义位置是否依赖对象数据签名特征
函数 (function)模块顶层,独立于任何对象不带self参数
方法 (method)impl块内,关联到 struct / enum是,可读取或修改实例数据第一个参数是self
关联函数 (associated function)impl块内,关联到 struct / enum否,不读取实例数据不带self参数

一句话概括:方法是"绑定在对象上的函数"(带self),关联函数则是"挂在类型命名空间下的函数"(不带self。三者在声明语法上高度统一,因此文档(index.md)给出了一套通用的函数声明模板。

函数声明模板

任何 Sway 函数声明都由以下组件构成:

  • fn关键字;
  • 一个唯一(unique)的函数名;
  • 可选的、逗号分隔的参数列表及其类型,放在()中;
  • 可选的返回类型。

来自 示例代码 lib.sw 的模板如下:

fn my_function(my_parameter: u64 /* ... */ ) -> u64 { // function code 42 }

注意模板中函数体最后一行42没有分号,这正是 Sway 的隐式返回语法——函数的最后一个表达式会直接作为返回值(详见后文"返回值"章节)。这一定义模板对函数、方法、关联函数同样适用。

独立函数:定义与调用

函数是不依附于任何对象的代码分组,适用于通用的计算逻辑。文档 function.md 以"判断两个数值是否相等"为例进行演示。

声明

下面的函数名为equals,接收两个u64(64 位无符号整数)参数,执行相等比较后隐式返回比较结果(类型为bool):

fn equals(first_parameter: u64, second_parameter: u64) -> bool { first_parameter == second_parameter }

这里first_parameter == second_parameter是最后一个表达式且不带分号,因此被隐式地作为返回值,无需书写return关键字。

调用

调用方式与大多数语言一致:函数名(实参, 实参)。示例代码演示了该函数的两种调用结果:

let result_one = equals(5, 5); // evaluates to `true` let result_two = equals(5, 6); // evaluates to `false`

从语法解析层面看,fn函数的声明在 Sway 编译器中由sway-ast的 item_fn.rs 定义抽象语法节点,并由 sway-parse 负责将源码解析为带函数名、参数列表、返回类型与函数体的语法结构,这保证了上述声明模板中各组件的顺序与类型约束在编译期即可被校验。

方法:绑定在对象上的函数

方法定义在impl块中,隶属于某个 struct(结构体)或 enum(枚举)。方法的第一个参数永远是self,它代表"正在被调用该方法的那一个实例",从而允许方法读取或修改实例的数据。

声明

文档以结构体为例(枚举的写法完全相同)。首先定义结构体:

struct Foo { bar: u64, }

然后使用impl(implementation,实现)关键字,后跟结构体名Foo,在块内定义属于该对象的方法:

impl Foo { // refer to `bar` fn add_number(self, number: u64) -> u64 { self.bar + number } // mutate `bar` fn increment(ref mut self, number: u64) { self.bar += number; } }

这段代码展示了方法的两种典型用途:

  • 读取实例数据add_number通过self.bar访问当前实例的字段,与参数number相加后返回新值(self按值传入);
  • 修改实例数据increment使用ref mut self声明对self可变引用,从而直接改写bar字段。注意修改型方法体内是语句(带分号),不需要返回任何值。

调用

调用方法使用点语法<变量名>.<方法名>()

let mut foo = Foo { bar: 42 }; let result = foo.add_number(5); // evaluates to `47` foo.increment(5); // `bar` inside `foo` has been changed from 42 to 47

由于increment会修改实例数据,调用它的变量必须先声明为mut。执行顺序上,add_number(5)返回47(42 + 5,不修改原值),随后increment(5)foo.bar从 42 修改为 47。

关联函数:挂在类型上的函数

关联函数与方法类似,同样定义在 struct 或 enum 的impl块中,但不使用结构体中的任何数据,因此不接收self参数

从语义上说,关联函数完全可以写成独立的顶层函数,但将其放进某个具体类型的impl块中,是出于组织与语义的考虑——让读者一眼就能看出"这个函数属于哪个类型"。这种做法常见于工厂函数、类型工具函数等场景。

构造器(Constructor)

关联函数中有一类特殊成员被称为类型构造器(type constructor)。构造器是"构造(实例化)一个新实例"的关联函数,其返回类型必然包含该类型本身,通常就直接是该类型。

Sway 有一个与构造器相关的重要可见性规则:字段为私有的公开 struct,必须提供一个公开构造器;否则,该结构体将无法在声明它的模块之外被实例化。这一设计让"创建实例"的唯一入口收敛到构造器上,便于模块作者控制对象的初始化过程。

声明

仍以上一节的结构体Foo为例:

impl Foo { // this is an associated function because it does not take `self` as a parameter // it is also a constructor because it instantiates // and returns a new instance of `Foo` fn new(number: u64) -> Self { Self { bar: number } } }

这里new是一个关联函数,因为它没有self参数;同时它也是一个构造器,因为它创建并返回了Foo的新实例。返回值类型写作Self,表示"当前正在实现的那个类型"(此处即Foo),这与 struct / enum 的 impl 语法 完全一致。

调用

关联函数不使用点语法,而是通过双冒号语法类型名::函数名()调用:

let foo = Foo::new(42);

返回值:显式返回与隐式返回

前面各节的示例中已经出现了返回值的不同写法,文档 return.md 对返回机制做了专门说明。Sway 提供两种返回方式:

  • 显式返回(Explicit Return):使用return关键字,后跟返回值并以分号结尾;
  • 隐式返回(Implicit Return):不使用return,直接让最后一个表达式作为返回值,且行尾不加分号

无论采用哪种方式,返回值的类型都必须与函数签名中声明的返回类型完全匹配。例如签名中第一个返回类型是u64,那么实际返回的第一个值也必须是u64

显式返回

显式返回在函数末尾最典型:

fn main() -> bool { return true; }

return表达式通常放在函数末尾,但它也可以出现在函数更早的位置,作为"满足某条件时提前退出函数"的机制。来自 explicit.sw 的示例展示了提前返回与多值返回(元组):

fn return_data(parameter_one: u64, parameter_two: bool) -> (bool, u64) { if parameter_two { return (!parameter_two, parameter_one + 42); } return (parameter_two, 42); }

parameter_twotrue时,函数在if分支内立即返回元组(!true, parameter_one + 42),不再执行后续代码;否则走到函数末尾返回(true, 42)。两条路径返回的都是(bool, u64)元组,与签名一致。

隐式返回

隐式返回省略return关键字,且最后一行不带分号

fn main() -> bool { true }

来自 implicit.sw 的完整示例演示了在if / else分支中隐式返回元组:

fn return_data(parameter_one: u64, parameter_two: bool) -> (bool, u64) { if parameter_two { (!parameter_two, parameter_one + 42) } else { (parameter_two, 42) } }

注意此写法下每个分支的最后一个表达式都隐式作为该分支的返回值,因此if / else整体构成函数的最后一个表达式。

两条返回路径的注意事项

  • 隐式返回是显式返回的一种特殊情况:它只能出现在函数末尾(即函数的最后一个表达式位置),不能像return那样在函数体中间提前返回;
  • 分号决定返回值:同一表达式"带分号是语句、不带分号是返回值"。若在函数末尾误加分号,函数将返回单元类型(),与期望的返回类型不匹配时会触发编译错误;
  • 提前退出必须用return:需要条件提前返回时只能使用显式return表达式。

小结

Sway 通过统一而简洁的语法,将函数(独立逻辑)、方法(self实例方法)与关联函数(类型命名空间下的工具函数 / 构造器)组织在同一套fn声明体系之下:

  • 独立函数用于通用逻辑,直接以fn name(params) -> Type声明,调用即写name(args)
  • 方法selfref mut self作为首参,通过点语法调用,可读取或修改实例数据;
  • 关联函数不带self,通过Type::name(args)调用,其中构造器负责实例化类型,并承担私有字段类型的对外构造职责;
  • 返回值支持末尾隐式返回(无分号的尾表达式)与任意位置的显式return两种形式,返回类型必须与签名严格一致。

完整可运行的示例代码位于 docs/reference/src/code/language/functions,其中lib.sw汇总了三种函数的声明与调用,explicit.swimplicit.sw分别演示两种返回写法。进一步探索函数在合约、脚本、库等程序类型中的应用,可继续阅读 程序类型文档 与仓库中的 examples 目录 下的合约示例。

【免费下载链接】sway🌴 Empowering everyone to build reliable and efficient smart contracts.项目地址: https://gitcode.com/GitHub_Trending/sw/sway

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询