Generics 范型

Generics 在计算机术语中被称为范型,引用 Rust Book 对于泛型的定义:泛型是具体类型或其他属性的抽象替代品。范型使得在编写 Sui Move 代码时提供更强的灵活性,并避免逻辑重复。

实际上,泛型允许我们只编写单个函数,写一套逻辑,而应用于任何类型上。所以这种函数也被称为模板 ——个可以应用于任何类型的模板处理程序。

范型是 Sui Move 中的一个关键概念,理解并对其工作原理保持直觉非常重要,因此请花点时间阅读本节并充分理解每个部分。

范型用法

在架构中使用范型

看一个基本示例,了解如何使用 Generics 创建一个可以容纳 Sui Move 中任何类型的容器 Box

首先,在没有范型的情况下,我们可以定义一个包含 u64 类型的 Box,如下所示:

#![allow(unused)]
fn main() {
module Storage {
    public struct Box {
        value: u64
    }
}
}

但是,这种类型只能保存 u64 类型的值,为了能够存储其他类型显然我们不能把所有类型的box都枚举完,所以这个时候就需要使用泛型。 代码将修改如下:

#![allow(unused)]
fn main() {
module Storage {
    public struct Box<T> {
        value: T
    }
}
}

能力限制

我们可以添加条件去强制传递给泛型的类型必须具有某些能力。 语法如下所示:

#![allow(unused)]
fn main() {
module Storage {
    // T must be copyable and droppable 
    public struct Box<T: store + drop> has key, store {
        value: T
    }
}
}

💡这里需要注意的是,由于外部容器类型,上例中的内部类型 T 必须满足一定的能力约束。 在这个例子中,T 必须有 store,因为 Boxstorekey。 但是,T 也可以具有容器没有的能力,如本例中的 drop

直觉是,如果允许容器包含一个不遵循它所遵循的相同规则的类型,容器将违反其自身的能力。 如果盒子里的东西不能被储存,那盒子怎么能被储存呢?

我们将在下一节中看到,在某些情况下,可以使用一种称为phantom 的特殊关键字来绕过此规则。

💡有关泛型类型的一些示例,请参阅 example_projects下的 泛型项目

在函数中使用Generics

要编写一个返回 Box 实例的函数,该实例可以为 value 字段接受任何类型的参数,我们还必须在函数定义中使用泛型。 该函数可以定义如下:

#![allow(unused)]
fn main() {
public fun create_box<T>(value: T): Box<T> {
        Box<T> { value }
    }
}

如果我们想限制函数只接受特定类型的 value,我们只需在函数签名中指定该类型,如下所示:

#![allow(unused)]
fn main() {
public fun create_box(value: u64): Box<u64> {
        Box<u64>{ value }
    }
}

这将只接受 u64 类型的输入,为了使用 create_box 的方法,同时仍然使用同样的泛型 Box 结构。

使用Generics调用函数

要调用带有包含泛型的签名的函数,我们必须在方括号中指定类型,如以下语法所示:

#![allow(unused)]
fn main() {
// value will be of type Storage::Box<bool>
    let bool_box = Storage::create_box<bool>(true);
// value will be of the type Storage::Box<u64>
    let u64_box = Storage::create_box<u64>(1000000);
}

使用运用Sui CLI的Generics调用函数

要从 Sui CLI 调用其签名中带有泛型的函数,您必须使用标志 --type-args 定义参数的类型。

以下示例调用 create_box 函数创建一个盒子,其中包含 0x2::sui::SUI 类型的硬币:

sui client call --package $PACKAGE --module $MODULE --function "create_box" --args $OBJECT_ID --type-args "0x2::coin::Coin<0x2::sui::SUI>" --gas-budget 10000

高级 Generics 语法

有关 Sui Move 中涉及使用的更多的泛型高级语法,例如多个泛型类型,请参阅 Move Book 中关于 Generic 的部分

但是对于我们当前关于同质化代币的课程,您已经足够了解泛型是如何运行的。