Skip to content

结构体和消息

Tact 支持多种为智能合约使用定制的基本数据类型。然而,使用单独的存储方式往往变得繁琐,因此有了结构体(Structs)和消息(Messages),这些可以将不同类型组合在一起。

警告:当前不支持循环类型。这意味着结构体/消息 A 不能包含一个结构体/消息 B 的字段,而 B 又包含一个结构体/消息 A 的字段。

因此,以下代码将无法编译:

solidity
struct A {
    circularFieldA: B;
}
 
struct B {
    impossibleFieldB: A;
}

结构体

结构体可以定义包含多个不同类型字段的复杂数据类型。它们也可以嵌套。

solidity
struct Point {
    x: Int as int64;
    y: Int as int64;
}
 
struct Line {
    start: Point;
    end: Point;
}

结构体还可以包括默认字段和可选字段。当你有许多字段但不想重复指定它们时,这会非常有用。

solidity
struct Params {
    name: String = "Satoshi";  // 默认值
    age: Int?;                 // 可选字段
    point: Point;              // 嵌套结构体
}

结构体也用作从 getter 或其他内部函数返回的返回值。它们有效地允许单个 getter 返回多个返回值。

solidity
contract StructsShowcase {
    params: Params; // 结构体作为合约持久状态变量
 
    init() {
        self.params = Params{point: Point{x: 4, y: 2}};
    }
 
    get fun params(): Params {
        return self.params;
    }
}

字段的顺序无关紧要。与其他语言不同,Tact 之间的字段没有任何填充。

消息

消息可以包含结构体:

solidity
struct Point {
    x: Int;
    y: Int;
}
 
message Add {
    point: Point; // 包含一个结构体 Point
}

消息与结构体几乎相同,唯一的区别是消息在其序列化中包含一个 32 位整数头,其中包含它们的唯一数字 ID。这允许消息与接收器一起使用,因为合约可以根据这个 ID 区分不同类型的消息。

Tact 会为每个接收到的消息自动生成这些唯一的 ID,但这可以手动覆盖:

solidity
// 此消息用 0x7362d09c 覆盖其唯一 ID
message(0x7362d09c) TokenNotification {
    forwardPayload: Slice as remaining;
}

这在你想要处理给定智能合约的某些操作码(operation codes)时非常有用,例如 Jetton 标准。这里给出了该合约能够处理的操作码(opcodes)简表,在 FunC 中。。它们作为智能合约的接口。

有关更多深入信息,请参阅: