struct
module book::obj {
public struct Color {
red: u8,
green: u8,
blue: u8,
}
}
对象
- 要说明白Sui的对象模型得先从先从Sui的链上数据存储模型说起
- 对象在Sui上存储,维护了一个全局的Map数据结构 Map<ID,object>, 学过数据结构的都知道Map结构也可以理解成事HashMap的结构就是 key 是id,值是Object, id 肯定是唯一的,通过这个唯一的id 查找到object
如何定义一个对象
- 必须有
key
能力 - 必须第一个字段 是id,而且类型为
sui::object::UID
module book::obj {
use sui::object::UID;
public struct Obj has key {
id:UID,
}
}
module book::obj {
use sui::object::UID;
public struct ColorObject has key {
id: UID,
red: u8,
green: u8,
blue: u8,
}
}
代表ColorObject
一个 Sui 对象类型,您可以使用它来创建最终可以存储在 Sui 网络上的 Sui 对象
- 这是会报错的
module book::obj {
public struct Obj has key {
a:u64
}
}
- 这不是一个对象,只是一个普通数据结构
module book::obj {
public struct Obj1 {
a:u64,
b:u64
}
public struct Obj2 has store {
a:u64,
b:u64
}
}
UID 类型的说明
定义在Sui的标准库中,具体标准库是什么会在后面又详细的说明,我们一起看一下UID的定义
/// Sui object identifiers
module sui::object {
use std::bcs;
use sui::address;
use sui::tx_context::{Self, TxContext};
public struct ID has copy, drop, store {
// We use `address` instead of `vector<u8>` here because `address` has a more
// compact serialization. `address` is serialized as a BCS fixed-length sequence,
// which saves us the length prefix we would pay for if this were `vector<u8>`.
// See https://github.com/diem/bcs#fixed-and-variable-length-sequences.
bytes: address
}
/// Globally unique IDs that define an object's ID in storage. Any Sui Object, that is a struct
/// with the `key` ability, must have `id: UID` as its first field.
/// These are globally unique in the sense that no two values of type `UID` are ever equal, in
/// other words for any two values `id1: UID` and `id2: UID`, `id1` != `id2`.
/// This is a privileged type that can only be derived from a `TxContext`.
/// `UID` doesn't have the `drop` ability, so deleting a `UID` requires a call to `delete`.
public struct UID has store {
id: ID,
}
// === any object ===
/// Create a new object. Returns the `UID` that must be stored in a Sui object.
/// This is the only way to create `UID`s.
public fun new(ctx: &mut TxContext): UID {
UID {
id: ID { bytes: tx_context::fresh_object_address(ctx) },
}
}
public fun delete(id: UID) {
let UID { id: ID { bytes } } = id;
delete_impl(bytes)
}
}
创建 Sui 对象
严格来说,上面的代码只是定义好了 object 的模板,并不能说已经是object了,怎么理解这个呢 就像生产一个鼠标,我们只是做好了鼠标的模具,需要用这个模具来真正生产出具体的鼠标了, 这个鼠标才能算真正的对象,那么如何用我们定义好的对象模板生产出真正的对象, 其实如果你有其他编程语言基础的话你可能会很容易理解, 我们已经定义好了一个对象模板,需要生成一个对象实例,具体的代码如下
module book::obj {
use sui::object;
use sui::object::UID;
// tx_context::TxContext creates an alias to the TxContext struct in the tx_context module.
use sui::tx_context::TxContext;
public struct ColorObject has key {
id: UID,
red: u8,
green: u8,
blue: u8,
}
fun new(red: u8, green: u8, blue: u8, ctx: &mut TxContext): ColorObject {
ColorObject {
id: object::new(ctx),
red,
green,
blue,
}
}
}
定义 Sui 对象类型模板后,您可以创建或实例化 Sui 对象。 要从其类型创建一个新的 Sui 对象,您必须为每个字段分配一个初始值, 包括id. 为 Sui 对象创建新对象的唯一方法UID是调用object::new. 该new函数将当前事务上下文作为生成唯一 ID 的参数
module book::obj {
use sui::object::UID;
use sui::transfer;
use sui::tx_context::{Self, TxContext};
use sui::object;
public struct Obj has key {
id: UID,
}
fun init(ctx: &mut TxContext) {
let obj = Obj {
id: object::new(ctx)
};
transfer::transfer(obj, tx_context::sender(ctx))
}
}
正如代码所看到的,创建出来的实例,需要调用标准库的方法转移,这就是我们接下来需要讲到的 object owner模型 也叫对象所有权,但是在这之前 我们先看一下对象的内部其他信息
对象内部元数据
每个 Sui 对象都有以下元数据:
一个 32 字节的全局唯一 ID。对象 ID 源自创建对象的交易摘要和对交易生成的 ID 数量进行编码的计数器。 一个 8 字节无符号整数版本,随着每个读取或写入它的事务单调增加。 一个 32 字节的交易摘要,指示包含此对象作为输出的最后一笔交易。 一个 21 字节的所有者字段,指示如何访问此对象。对象所有权将在下一节中详细解释