Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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(&registry.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 funpublic 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 buildsui 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 mutpublic structpublic(package)、方法语法、索引语法、枚举和模式匹配等特性,大幅提升了语言的表达力和开发体验。这些改进使 Move 代码更简洁、更安全、更易读。本书后续所有代码都将使用 Move 2024 语法。如果你需要迁移旧代码,可以使用 sui move migrate 工具自动完成大部分转换。