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 字节的所有者字段,指示如何访问此对象。对象所有权将在下一节中详细解释