Skip to content

Latest commit

 

History

History
136 lines (93 loc) · 3.79 KB

03-object.md

File metadata and controls

136 lines (93 loc) · 3.79 KB

object:UID 是对象身份,ID 是可复制门牌

第二卷 · 第 03 章 · ★★★

官方源码:object.move 配套示例:examples/tests/v2_object_transfer_tests.move

本章读完你会

  1. 能区分 UID 与 ID。
  2. 知道 has key 对象为什么必须有 id: UID。
  3. 能解释对象创建、读取 ID、删除的完整生命周期。

1. 对象最小形状

一个普通 Sui 对象通常长这样:

public struct Note has key {
    id: UID,
    text: String,
}

这段代码里有三个关键点:

  • has key:说明它可以成为链上对象根。
  • id: UID:说明它有唯一对象身份。
  • id 是首字段:这是 Sui 对象模型约定。

没有 UID,它只是普通 Move 值;有 UID 且 has key,它才能进入对象存储。

2. UID 与 ID

项目 UID ID
是否可复制 不可复制 可复制
是否可丢弃 不可随便丢弃 可丢弃
代表什么 对象身份本体 对象地址句柄
常见用途 对象字段、删除时消费 事件、索引、引用
是否等于权限 持有对象才有操作权 只是门牌,不是钥匙

最重要的比喻:

UID = 地契
ID  = 门牌复印件

别人知道你的对象 ID,不代表能修改你的对象。

3. 创建对象

对象创建通常是:

let id = object::new(ctx);
let obj = Note { id, text };
transfer::transfer(obj, tx_context::sender(ctx));

学习重点:

  • object::new(ctx) 创建 UID。
  • ctx 确保新对象地址来自本笔交易。
  • 创建后必须处理对象:转移、共享、冻结或删除。
  • 不能创建后让资源悬空。

4. 删除对象

如果要销毁对象,必须消费 UID:

let Note { id, text } = note;
object::delete(id);

如果对象里还有不能丢弃的资源,例如 Balance<T>、Coin<T>、Table<K,V>,必须先处理它们:

  • 提款。
  • 清空。
  • 销毁零值。
  • destroy_empty。
  • 转移给别人。

删除对象不是“把 struct 丢掉”,而是按资源规则逐个收尾。

5. 系统单例对象

Sui Framework 中有一些固定 ID 的系统对象:

对象 典型 ID 用途
Clock 0x6 链上时间
Random 0x8 链上随机
SystemState 0x5 系统状态,本书不深讲
DenyList 等 见源码 策略与合规路径

应用代码通常通过类型化对象使用它们,而不是到处手写十六进制地址。

6. 常见错误

  • 把 ID 当作权限。
  • 创建对象后没有转移或删除。
  • 删除对象时忘记 object::delete(id)。
  • 对象里有非 drop 字段却试图直接丢弃。
  • 在事件里记录了 ID,就以为对象一定还存在。

事件只是历史记录;对象是否还存在,要看链上状态。

7. 练习路径

写一个 Note 对象:

  1. create(text, ctx):创建并转给 sender。
  2. update(&mut Note, new_text, ctx):只有 owner 或字段 owner 可以改。
  3. delete(Note):消费对象并删除 UID。
  4. 测试 Alice 创建、修改、删除。
  5. 测试 Bob 不能操作 Alice 的对象。

8. 本章小结

UID 是对象身份本体,ID 是可复制引用。Sui 对象模型的安全性来自:身份不能伪造,资源不能随便丢弃,所有权变化必须走明确路径。

9. 自测题

  1. 为什么 ID 可以复制而 UID 不行?
  2. 删除对象时为什么必须调用 object::delete?
  3. 如果对象里有 Balance<SUI>,删除前要做什么?
  4. 事件里的对象 ID 能否证明对象仍然存在?

10. 延伸阅读