Sui Move: 最小的存储单元-对象

目录

对象的结构

元数据

内容

结构体对象

删除对象

对象的分类

独有对象

创建方法

使用场景

不可变对象

创建方法

访问方法

使用场景

共享对象

创建方法

访问方法

使用场景

被嵌套的对象

直接嵌套

创建方式

访问方式

解除嵌套

应用场景

通过Option嵌套

创建方式

访问方式

解除嵌套

应用场景

通过vector嵌套

创建方式

访问方式

解除嵌套

应用场景


有过后端编程经验的小伙伴会发现:无论什么语言核心其实都是对数据的增删改查,Sui Move也不例外,但是Sui Move并不会跟其他语言一样连接数据库、使用特定的数据库语言存储数据,而是使用对象作为最小的存储单元。也就是说如果你想持久化一些数据,先申明一个对象模型,使用要存储的数据实例化对象即可。如下:

//申明对象模型
struct Article has key {
    id: object::UID,
    title: string::String,
    content: string::String,
    word_cnt: u64,
}
public fun new(title: vector<u8>, content: vector<u8>, ctx: &mut tx_context::TxContext) {
 	let content = string::utf8(content);
    //实例化一个对象
    let article = Article{
        id: object::new(ctx),
        title: string::utf8(title),
        content: content,
        word_cnt: string::length(&content),
    };
	//对象设置为共享对象,所有用户皆可访问修改
    transfer::share_object<Article>(article);
}

在发布这段代码后,调用new方法就可以生成一个对象并返回对象的元数据,对象也保存在了链上。

对象模型是一种特殊的结构体,所以上一章讲到的结构体相关的用法对象也一样适用。那如何区分这是一个普通的结构体还是对象呢?对象一定具有key能力且对象的第一个字段是全局唯一ID ,这个全局唯一id可以确定对象在链上的位置,所以也可以理解为就是对象的地址。对象的其他字段则可以是基础数据类型、对象或者非对象结构体。

第一章我们也讲过,在发布代码的时候会返回一个所有者为Immutable(不可改变的)的对象,这个对象的ID就是对应的包地址。这句话隐含了一个信息,就是我们发布的包也是一个对象。这个对象永远不可改变或删除。所以发布代码的过程也可以理解为是把代码存储到区块链的过程。

对象的结构

使用sui client object 就可以看到对象的完整信息,无论是包还是结构体对象都可以执行这个命令。结果如下:

结构体对象:

object.jpg

包:

package.jpg

我们可以把对象分为两部分:元数据和内容。

元数据

以下是无论是对象模型还是包都有的公共元数据:

  • 32个字节的全球唯一标识符(objectId),也就是对象ID,也可以说是对象的地址。
  • 8个字节的版本号(version),每次修改对象都会加一。
  • 32个字节的交易的摘要(prevTx),记录最后一次输出这个对象的交易。
  • 33个字节的owner字段,对象的所有者,也可以根据这个字段推测如何访问这个对象。
  • objectType则指明对象类型,值可能是package可能是自定义的结构体类型。
  • digest字段是这个对象元数据和内容的哈希,也就是对象的摘要。
  • storageRebate字段表示,如果这个对象后期在链上删除,将会返还的gas值。
内容

对象内容就一个content字段,它里面的

dataType字段用于区分是结构体对象(moveObject)还是包(package)。

content字段的其他内容则因类型的不同而各有区别了。

结构体对象
  • type字段:表明结构体类型
  • hasPublicTransfer字段:是否能使用publish_transfer转移所有权,上图这个对象因为是共享对象所以不能被转移所有权,值为false。
  • fields字段就是对象的键值对,使用BCS(Binary Canonical Serialization)编码。我们可以在sui client object命令中指定--bcs选项来查看编码后的值。

Move Packages包含包中的代码。查看上图可以发现引用包的名称已经自动变成了包的地址。

删除对象

我们上面说对象就是一种特殊的结构体,按理说上一章的销毁实例应该也适用于对象吧?我们按照上一章讲解的方法定义drop函数:

public fun drop(a: Article) {
    let Article{id:_,title:_,content:_,word_cnt:_}=a;
}

编译的时候直接报错:id字段Cannot ignore values without the 'drop' ability. The value must be used。id字段的类型是sui::object::UID,这个结构体类型没有drop的能力,所以不能丢弃id字段值。好在sui::object模块提供了一个删除UID的方法,也是删除对象id的唯一方法,如下:

//注意:要删除对象,必须按值传入
public fun drop(a: Article) {
    let Article{id:id,title:_,content:_,word_cnt:_}=a;
    object::delete(id);
}

我们发布合约后调用这个方法删除对象。在浏览器查看本次交易的费用明细可以发现:本次交易给我们返还了0.000351964 SUI!删除对象释放存储空间就会返还一部分gas,那我们在编码过程中应该积极删除无用对象,以减少gas消耗!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

积跬步DEV

如有帮助,那多谢赞助!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值