类型系统概述
Tact 程序中的每个变量、项目和值都有一个类型。 它们可以是
此外,这些类型中的许多类型可以变为空值。
原始类型
Tact 支持许多专为智能合约定制的原始数据类型:
Int
— Tact 中的所有数字都是 257 位有符号整数,但可以使用较小的表示方法来减少存储成本。Bool
— 经典布尔类型,具有true
和false
值。Address
— TON 区块链中的标准智能合约地址。Cell
、Builder
、Slice
— TVM 的底层基元。String
— 不可变的文本字符串。StringBuilder
— 辅助类型,允许以节省 gas 的方式连接字符串。
布尔值
原始类型 Bool
是经典的布尔类型,只能容纳两个值:true
和 false
。它便于布尔和逻辑运算,也便于存储标志。 它便于布尔和逻辑运算,也便于存储标志。
Tact 中没有隐式类型转换,因此两个布尔值的加法(+
)是不可能的。这里有许多比较运算符,例如: 这里有许多比较运算符,例如:
&&
为 logical AND||
为 logical OR!
为 logical inversion==
和!=
用于检查相等!
表示非空断言
将布尔值持久化到状态中非常节省空间,因为它们只占用1位。 在状态中存储 1000 个布尔值每年大约花费 TON。
复合类型
使用单独的存储手段往往会变得繁琐,因此有办法将多个原始类型组合在一起,创建复合类型:
除上述复合类型外,Tact 还提供了一种特殊的类型构造函数bounced<T>
,它只能在回退消息接收器(bounced message receivers)中指定。
请注意,虽然合约和trait也被视为Tact类型系统的一部分,但我们不能像结构体和消息那样传递它们。 相反,我们可以使用 initOf
表达式来获取给定合约的初始状态。
Maps
类型map<K, V>
用于将类型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 Messagemessage(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合约的所有functions、getters和receivers等多种内容。
合约示例:
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; }}
Traits
Tact 不支持经典的类继承,而是引入了trait(traits)的概念。它们的结构与抽象合约(类似于流行的面向对象语言中的抽象类)相同。 它们的结构与合约 相同,但不能初始化持久状态变量。
来自 @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; }}
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; }}