本篇文章学习四种能力,这在move语言中很重要
能力 (Abilities) 是 Move 独有的。拥有能力的类型才能和区块链进行交互。能力赋予指定类型操作的特殊注释,并通过控制类型的操作方式来帮助加强智能合约开发的安全性和正确性。
能力 (Abilities) 是结构体声明和定义时即被赋予的。被赋予能力的实例将继承该能力。不是只有结构体才可被赋予能力,其它类型的实例也可以继承能力,只要该类型被赋予指定的能力。
has 是用于赋予类型能力 (Abilities) 的关键词。
copy:
允许复制结构体的实例,即允许复制对象。Move 是面向资源管理的语言,像 Coin 之类的对象是不允许复制的(如同现实世界中你不允许通过复印现金来获取更多财富),因此需要使用 copy 能力来明确地指定哪些对象可以被复制。drop:
允许删除或丢弃结构体的实例,拥有该能力的对象可以通过自动解构(析构)来实现删除的目的,而不需要我们手动删除。store:
允许结构体的对象在全局存储中持久化,从而在多个交易之间共享和管理资源。并且可以作为其他对象的字段,从而创建复杂的数据结构。key:
允许该结构体实例被全局存储和查找,拥有该能力的对象会有一个全局唯一的 ID 以便在 Sui 全局存储中进行查找和使用。同时,Move 的能力功能让智能合约回避了一些常见的问题:
store
和 key
管理与区块链全局存储交互的数据。没有 key
的类型将无法与区块链的全局存储交互,从而确保区块链状态的受控和安全操作。copy
和 drop
功能强制执行这些规则。在 Move 的语法,虽然原生类型可以自然的拥有 copy 和 drop 能力,但其它类型却必须明确地被指明它们的能力 (Abilities) 。
因为 Move 是为了表达数字资产和资源为设计的,不能任意复制是一个重要的特征。因此,Move 特地为此设计了 copy 能力。
⚠️ 注意:动态数组 (vector) 虽无需明确地指明它的能力,但它的类型 T必须具备特定操作所需的能力。
copy 能力语法格式如下:
<visibility modifier> <type> <name> has copy {}
在下面的例子中,被赋予 copy 能力后,hello
实例可以轻松地被复制,a 被复制到 b,然后使用解引用操作符复制到 c
1public struct hello has copy {}
2
3let a = hello {};
4let b = a; // `a` 被复制到 `b`
5let c = *&b;
我们一直强调 Move 是一个注重资源管理的语言,当一些实例不再被需要时,就需要清理,以腾出空间。这时, drop 就发挥作用了。这个小举动在一些普遍的语言是默认的,比如自动垃圾收集 (Automatic Garbage Collection),但 Move 则需要手动处理。如果没处理好,编译器可能会出现错误。这种处理资源的方法看似麻烦,但可以让程序员在编译时就发现问题,而不是在应用程序运行时才出现问题。这对于编辑去中心化应用 (DApp) 来说是很重要的。
drop 能力语法格式如下:
<visibility modifier> <type> <name> has drop {}
和 copy 一样,如果一个类型没被赋予 drop 能力,要访问就必须先解构。同样,要删除不再需要的实例时,没有 drop 能力的类型也需要先进行解构操作
⚠️ 注意: 不能任意 copy 资源是 Move 为了安全表达数字资产和资源为设计的。 而 drop 的设计让以不被需要的实例可以轻松删除。那么,如果要确定实例没有被无故删除,那么就不要给类型赋予 drop 能力。这样一来,就可以确保该资源会被处理妥当。
module hello::drop_ability {
use std::string::{ utf8, String};
public struct DropMe has drop {
id: u8,
name: String,
}
public struct NoDrop {}
#[test]
fun test_ignore() {
// 创建 DropMe 结构的实例并自动忽略它。
let _ = DropMe { id: 1, name: utf8(b"hello") };
// 必须手动解构来忽略 no_drop 实例
let no_drop = NoDrop {};
let NoDrop {} = no_drop;
}
}
在 Move 语言中,key 和 store 能力和区块链的全局存储有紧密相连。 key 主要用于标识类型在存储作为键 (key) 的功能。被赋予 key 能力的类型可以直接被用户,即 address 拥有。
在 Sui 中,key 能力必须与唯一标识符(UID)相结合使用,以确保资源的唯一性和可追踪性。UID 是一个全局唯一的标识符,用于标识特定的资源或对象。这也使拥有 key 的结构体类型被视为对象。
public struct MyObject has key, store {
id: UID, // required
name: String,
}
public fun new(name: String, ctx: &mut TxContext): MyObject {
MyObject {
id: object::new(ctx),
name,
}
}
在这个例子中,MyObject
结构体包含一个 UID 字段,并具有 key 和 store 能力。UID 用于唯一标识每个对象,使其在全局存储中保持唯一性和安全性。
key 可以与 copy 和 drop 一起使用吗?
A:具有 key 能力的对象不能同时具有 copy 和 drop 能力。原因如下:
store 能力允许对象在全局存储中被持久化。store 能力与 key 能力常常结合使用,以确保对象既可以唯一标识又可以在全局存储中进行自由转移。拥有 store 能力的类型可以作为其他对象的字段,从而创建复杂的数据结构。
/// sui::Balance 结构体有 `store` 能力
public struct Balance<phantom T> has store {
value: u64
}
/// sui::Coin 结构体具有 key + store 的能力,其中 Balance 以字段的形式包装在 Coin 中
public struct Coin<phantom T> has key, store {
id: UID,
balance: Balance<T>
}
在这个例子中, Coin 同时拥有 key 和 store 的能力,它可以由其 owner 进行自由的转移,即我们常见的转账操作。而 Balance 具有 store 能力,它作为 Coin 的字段,同样存储在 Sui 的全局存储中。
具有 key 和 key + store 能力的对象有什么区别?
A:只有 key 能力的对象:
具有 key + store 能力的对象:
具有 key 能力的对象如果没有 store 能力,就不能在全局存储中被自由转移,这样设计的目的是确保一些重要资源的稳定性和安全性。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!