跳转到内容

类型系统概述

Tact 程序中的每个变量、项目和值都有一个类型。 它们可以是

此外,这些类型中的许多类型可以变为空值

原始类型

Tact 支持许多专为智能合约定制的原始数据类型:

  • Int — Tact 中的所有数字都是 257 位有符号整数,但可以使用较小的表示方法来减少存储成本。
  • Bool — 经典布尔类型,具有 truefalse 值。
  • Address — TON 区块链中的标准智能合约地址
  • CellBuilderSliceTVM 的底层基元。
  • String — 不可变的文本字符串。
  • StringBuilder — 辅助类型,允许以节省 gas 的方式连接字符串。

布尔值

原始类型 Bool 是经典的布尔类型,只能容纳两个值:truefalse。它便于布尔和逻辑运算,也便于存储标志。 它便于布尔和逻辑运算,也便于存储标志。

Tact 中没有隐式类型转换,因此两个布尔值的加法(+)是不可能的。这里有许多比较运算符,例如: 这里有许多比较运算符,例如:

将布尔值持久化到状态中非常节省空间,因为它们只占用1位。 在状态中存储 1000 个布尔值每年大约花费 0.000720.00072 TON。

复合类型

使用单独的存储手段往往会变得繁琐,因此有办法将多个原始类型组合在一起,创建复合类型:

除上述复合类型外,Tact 还提供了一种特殊的类型构造函数bounced<T>,它只能在回退消息接收器(bounced message receivers)中指定。

请注意,虽然合约trait也被视为Tact类型系统的一部分,但我们不能像结构体和消息那样传递它们。 相反,我们可以使用 initOf表达式来获取给定合约的初始状态。

Maps

类型map<K, V>用于将类型K的键与类型V的相应值关联起来。

示例map<K, V>

let mapExample: map<Int, Int> = emptyMap(); // empty map with Int keys and values

在专用页面了解更多关于他们的信息: Maps

结构和消息

结构消息是将多个原始类型组合成复合类型的两种主要方式。

Struct 示例:

struct Point {
x: Int;
y: Int;
}

Message 示例:

// Custom numeric id of the Message
message(0x11111111) SetValue {
key: Int;
value: Int?; // Optional, Int or null
coins: Int as coins; // Serialization into TL-B types
}

有关它们的更多消息,请访问专门页面:结构和消息

可选项

所有原始类型以及结构体和消息都可以为空,并持有一个特殊的 null值。

可选项示例:

let opt: Int? = null; // Int or null, with explicitly assigned null

在专门页面了解更多信息:可选项

合约

TON区块链上的合约在Tact中作为智能合约的主要入口。 它包含了一个TON合约的所有functionsgettersreceivers等多种内容。

合约示例

contract HelloWorld {
// Persistent state variable
counter: Int;
// Constructor function init(), where all the variables are initialized
init() {
self.counter = 0;
}
// Internal message receiver, which responds to a string message "increment"
receive("increment") {
self.counter += 1;
}
// Getter function with return type Int
get fun counter(): Int {
return self.counter;
}
}

or Contracts and Traits

Traits

Tact 不支持经典的类继承,而是引入了trait(traits)的概念。它们的结构与抽象合约(类似于流行的面向对象语言中的抽象类)相同。 它们的结构与合约 相同,但不能初始化持久状态变量

trait还可以让继承它的合约重写其函数的行为和常量的值。

来自 @stdlib/ownable 的 trait Ownable 示例:

trait Ownable {
// Persistent state variable, which cannot be initialized in the trait
owner: Address;
// Internal function
fun requireOwner() {
nativeThrowUnless(132, context().sender == self.owner);
}
// Getter function with return type Address
get fun owner(): Address {
return self.owner;
}
}

合约 使用了 trait Ownable

contract Treasure with Ownable {
// Persistent state variable, which MUST be defined in the contract
owner: Address;
// Constructor function init(), where all the variables are initialized
init(owner: Address) {
self.owner = owner;
}
}