Move 2024 版本新特性
Move 2024 是 Move 语言的一次重要更新,引入了大量现代化的语法特性,使代码更简洁、更符合直觉。本书所有代码均基于 Move 2024 版本编写。本节将详细介绍这些新特性,并通过前后对比帮助你理解每项改进。
启用 Move 2024
在 Move.toml 中设置版本:
[package]
name = "my_package"
edition = "2024"
[dependencies]
Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "framework/mainnet" }
[addresses]
my_package = "0x0"
重要:
edition = "2024"必须在[package]下显式声明。如果省略,默认使用旧版本语法。
可变绑定:let mut
Move 2024 要求显式标注可变变量,使代码意图更清晰。
旧版本
let x = 5;
x = 10; // 隐式可变,容易产生误解
新版本
let mut x = 5;
x = 10; // 显式声明可变性
let y = 5;
// y = 10; // 编译错误!未声明 mut
这一改变与 Rust 的 let mut 一致,让开发者在声明时就明确变量是否会被修改。函数参数同样适用:
public fun process(mut value: u64): u64 {
value = value + 1;
value
}
结构体可见性:public struct
结构体声明现在需要显式指定可见性。
旧版本
struct MyStruct has key {
id: UID,
value: u64,
}
新版本
public struct MyStruct has key {
id: UID,
value: u64,
}
如果结构体只在模块内部使用,可以省略 public:
struct InternalConfig {
max_retries: u64,
timeout_ms: u64,
}
包可见性:public(package) 替代 friend
friend 机制已被弃用,取而代之的是更简洁的 public(package) 可见性。
旧版本
module my_package::module_a {
friend my_package::module_b;
public(friend) fun internal_helper(): u64 {
42
}
}
新版本
module my_package::module_a;
public(package) fun internal_helper(): u64 {
42
}
public(package) 允许同一包内的所有模块调用该函数,无需逐一声明 friend 关系,更加灵活且易于维护。
三种函数可见性总结:
| 可见性 | 访问范围 | 使用场景 |
|---|---|---|
fun | 仅当前模块 | 内部辅助函数 |
public(package) | 同一包内的所有模块 | 包内共享逻辑 |
public | 任何模块 | 对外公开的 API |
方法语法:接收者风格调用
Move 2024 支持使用 . 语法在结构体实例上调用方法,类似于面向对象语言。
旧版本
let len = vector::length(&my_vec);
let val = vector::borrow(&my_vec, 0);
vector::push_back(&mut my_vec, 42);
新版本
let len = my_vec.length();
let val = my_vec.borrow(0);
my_vec.push_back(42);
编译器会自动将 e.f(args) 转换为 f(e, args),其中 e 作为第一个参数传入。这要求函数的第一个参数类型与调用者匹配。
自定义结构体同样支持方法语法:
public struct Counter has key {
id: UID,
value: u64,
}
public fun increment(counter: &mut Counter) {
counter.value = counter.value + 1;
}
// 调用时可以写成:
// counter.increment();
内置类型方法
Move 2024 为基本类型和内置类型添加了便捷方法。
字节串转 String
// 旧版本
use std::string;
let s = string::utf8(b"Hello, Move!");
// 新版本
let s = b"Hello, Move!".to_string();
地址转字节
// 旧版本
use sui::address;
let bytes = address::to_bytes(@0xa11ce);
// 新版本
let bytes = @0xa11ce.to_bytes();
常用方法一览
// vector 方法
let mut v = vector[1, 2, 3];
v.push_back(4);
let len = v.length();
let first = v[0]; // 索引访问
let is_empty = v.is_empty();
// u64 方法
let s = 42u64.to_string();
索引语法
使用 [] 操作符直接访问集合元素,替代冗长的 borrow 调用。
旧版本
let val = *vector::borrow(&my_vec, 0);
*vector::borrow_mut(&mut my_vec, 1) = 42;
新版本
let val = my_vec[0]; // 不可变索引
my_vec[1] = 42; // 可变索引
对于自定义类型,可以通过 #[syntax(index)] 属性实现索引访问:
public struct Registry has key {
id: UID,
entries: Table<address, u64>,
}
#[syntax(index)]
public fun borrow_entry(registry: &Registry, addr: address): &u64 {
table::borrow(®istry.entries, addr)
}
#[syntax(index)]
public fun borrow_entry_mut(registry: &mut Registry, addr: address): &mut u64 {
table::borrow_mut(&mut registry.entries, addr)
}
// 使用:
// let value = registry[addr];
// registry[addr] = 100;
方法别名
use fun 和 public use fun 允许你为类型关联自定义方法名。
module my_package::my_module;
use sui::coin::Coin;
use sui::sui::SUI;
public use fun coin_value as Coin<SUI>.value;
public fun coin_value(coin: &Coin<SUI>): u64 {
coin.value()
}
通过 use fun,你可以为不属于你的类型添加方法调用语法,增强代码可读性。
枚举类型与模式匹配
Move 2024 引入了枚举类型(enum)和 match 表达式,这是一项重大功能增强。
定义枚举
public enum Color has copy, drop {
Red,
Green,
Blue,
Custom { r: u8, g: u8, b: u8 },
}
模式匹配
public fun color_to_rgb(color: &Color): (u8, u8, u8) {
match (color) {
Color::Red => (255, 0, 0),
Color::Green => (0, 255, 0),
Color::Blue => (0, 0, 255),
Color::Custom { r, g, b } => (*r, *g, *b),
}
}
实际应用示例
public enum Action has copy, drop {
Transfer { to: address, amount: u64 },
Burn { amount: u64 },
Freeze,
}
public fun describe_action(action: &Action): String {
match (action) {
Action::Transfer { to: _, amount } => {
b"Transfer".to_string()
},
Action::Burn { amount: _ } => {
b"Burn".to_string()
},
Action::Freeze => {
b"Freeze".to_string()
},
}
}
注意:
match必须是穷尽的 —— 你必须覆盖枚举的所有变体,或使用通配符_作为兜底。
模块声明简化
Move 2024 允许省略模块的花括号包裹,整个文件即为一个模块:
旧版本
module my_package::my_module {
use std::string::String;
public fun hello(): String {
b"Hello".to_string()
}
}
新版本
module my_package::my_module;
use std::string::String;
public fun hello(): String {
b"Hello".to_string()
}
文件级模块声明以分号结尾,后续所有代码都属于该模块,更加简洁。
迁移工具
如果你有旧版本的 Move 代码需要迁移到 2024 版本,可以使用官方迁移工具:
sui move migrate
该工具会自动执行以下转换:
- 添加
mut标注 - 添加
public结构体可见性 - 将
friend+public(friend)替换为public(package) - 更新
Move.toml中的edition
提示:迁移工具会尽可能自动转换,但某些复杂情况可能需要手动调整。建议在迁移后运行
sui move build和sui move test确认一切正常。
特性对照表
| 特性 | 旧版本 | Move 2024 |
|---|---|---|
| 可变变量 | let x = 5; x = 10; | let mut x = 5; x = 10; |
| 结构体声明 | struct S {} | public struct S {} |
| 包内可见 | friend + public(friend) | public(package) |
| 方法调用 | vector::length(&v) | v.length() |
| 字节串转换 | string::utf8(b"hi") | b"hi".to_string() |
| 索引访问 | *vector::borrow(&v, 0) | v[0] |
| 模块声明 | module pkg::mod { ... } | module pkg::mod; |
| 枚举 | 不支持 | enum Color { Red, Blue } |
| 模式匹配 | 不支持 | match (x) { ... } |
小结
Move 2024 通过引入 let mut、public struct、public(package)、方法语法、索引语法、枚举和模式匹配等特性,大幅提升了语言的表达力和开发体验。这些改进使 Move 代码更简洁、更安全、更易读。本书后续所有代码都将使用 Move 2024 语法。如果你需要迁移旧代码,可以使用 sui move migrate 工具自动完成大部分转换。