Move —— 变量和可变性

Move 语言中变量默认是不可变的,这是出于安全性考虑的设计选择。本文介绍 Move 中变量的可变性控制、常量声明方式,以及遮蔽(Shadowing)机制如何在不同作用域中工作。

1. 可变与不可变变量

  • 不可变变量(Immutable):Move 中变量默认不可变,一旦绑定后值不能改变。
  • 可变变量(Mutable):使用 mut 关键字,可以让变量的值在绑定后发生改变。
1
2
3
4
5
6
7
// 可变变量
let mut x = 5;
x = 6; // ✅ 可以修改

// 不可变变量
let y = 10;
// y = 11; // ❌ 错误:不可修改

2. 常量(Constants)

  • 使用 const 关键字声明,始终不可变
  • 常量名全部大写,单词之间用下划线分隔
  • 常量必须在编译期已知,并且类型必须显式标注
  • 与变量不同,常量不能用 mut 声明
1
2
// 常量定义
const THREE_HOURS_IN_SECONDS: u32 = 60 * 60 * 3;

3. 遮蔽(Shadowing)

使用 let 重复声明同名变量时,新变量会 遮蔽 旧变量。

  • 在同一作用域内:旧绑定被完全隐藏,无法访问
  • 跨作用域时:内层遮蔽外层,内层作用域结束后外层绑定重新可见
1
2
3
4
5
6
7
8
9
public fun main() {
let x = 5;
let x = x + 1; // 新的 x 遮蔽旧的 x=5
{
let x = x * 2; // 仅在当前作用域生效,不会遮蔽前面的x = x + 1
debug::print(&x); // 输出 12
}
debug::print(&x); // 输出 6
}

3.1 与 mut 的区别

  • mut:修改同一个变量的值。
  • 遮蔽:创建一个新的变量绑定,旧的绑定被隐藏,而且可以改变类型。
1
2
3
4
5
6
7
// 使用 mut:错误
let mut num: u8 = 32;
// num = 256; // ❌ 类型不匹配,256 超出了 u8 的范围

// 使用遮蔽:正确
let num: u8 = 16;
let num: u16 = 256; // ✅ 类型从 u8 → u16