|
Tact 支持许多专为智能合约使用而定制的 原始数据类型。 不过,使用单独的存储方式往往会变得繁琐,因此有 Structs 和 Messages可以将类型组合在一起。 不过,使用单独的存储方式往往会变得繁琐,因此有 Structs 和 Messages可以将类型组合在一起。
( K, M3 T2 x# j+ ~ [
: a. Y4 q+ Z# d! e5 k8 t8 r& K- U
. X5 B0 Q7 N1 ~' A; z
' e1 H" I H {. b( h" o结构
( |. c8 [3 y, l G/ e/ v' W结构体可以定义包含多个不同类型字段的复杂数据类型。 它们还可以嵌套。 它们还可以嵌套。! b& g' V6 Z, N* F/ p6 r
- struct Point {
$ E* `& G1 ]/ k5 A4 y' ] - x: Int as int64;4 E$ x: ^4 ~4 W; ?5 ]$ y
- y: Int as int64;
/ d* S( D/ C2 h: {$ @) S) ?2 ]& `- K0 G - }3 k b$ X" N) n: D
6 x+ U# l1 {0 V. Z" ]9 e- struct Line {3 l! v0 T* \9 Q3 @
- start: Point;0 v$ x3 w! l, o# Q) h: i
- end: Point;
& G. N' }) v. f& R/ T - }
复制代码 结构体还可以包含默认字段,并定义可选类型的字段。 结构体还可以包含默认字段和定义[可选类型]字段(/book/optionals)。 如果您有很多字段,但又不想一直在 new instances 中为它们指定通用值,那么这将非常有用。
. H; e2 \, s$ W; r2 T- struct Params {! K+ F( e9 N0 o" ?) z
- name: String = "Satoshi"; // default value
* w! D- N( S+ x - $ V- M e# v3 R7 g9 A
- age: Int?; // field with an optional type Int?
" n* `4 Q" {3 @4 ^8 x+ S4 ^ - // and default value of null
3 r$ K [$ a% F& a: ^
' {! x" p1 ?" Q8 R7 O ~- F P- point: Point; // nested Structs
7 @( m( R1 s: r6 [0 a% H5 @& \$ \ - }
复制代码 字段的顺序很重要,因为它与TL-B 模式 中的内存布局一致。 不过,与某些采用手动内存管理的语言不同,Tact 在字段之间没有任何填充。
" T7 M+ y# K) S$ @% J4 ~. r; G9 @
$ r: t% L! V4 p4 G
j8 R1 {2 K4 L) N1 I% i/ g% B9 x. y* M3 b5 S8 \5 X
消息$ {3 }( s3 y) d# E: H4 N0 N) g
消息中可以包含 结构体:
7 d& T& b0 J3 Z5 ^* d- struct Point {# f/ l# Y4 d5 o2 c7 [
- x: Int;$ I! M) _1 k- C! J2 R3 B
- y: Int;
7 }! n& }1 G1 Z$ X - }$ u& K0 M* Q' s
- 5 ^8 c+ d. i4 g
- message Add {1 c- M3 c0 i9 R& g
- point: Point; // holds a struct Point
6 e2 G8 f. P" I% q* U7 H4 w - }
复制代码- // This Message overwrites its unique id with 0x7362d09c0 u3 @$ T4 k+ I5 u1 h
- message(0x7362d09c) TokenNotification {# y6 ^: K, B' L
- forwardPayload: Slice as remaining;( H# u+ b4 f" }/ t6 o( Q" B
- }
复制代码 这对于要处理特定智能合约的某些操作码(如 Jetton standard)的情况非常有用。 该合约能够处理的操作码简表为此处以 FunC 表示。 它们是智能合约的接口。/ @ Q5 c# O* O3 }3 Z$ A
9 Y4 ^, D, g: E6 d6 q, b2 R& P7 t1 F& y
8 c9 X2 m9 Z0 P( _: G操作! u/ @# L. U. x: |9 g
实例化
& h/ O! t7 J, i) e, h) J, B$ }$ |( h创建 Struct 和 Message 实例类似于 function calls,但需要用大括号 {}(大括号)代替小括号 ()指定参数:
5 u5 w* N$ a9 S+ X% k2 i- e* V- struct StA {3 I; _, k l2 l Y8 [1 ~
- field1: Int;
( x3 a- X- d0 r5 n6 g8 v* h# k - field2: Int;
+ k' `; Z* ]* f. s1 V" { - }, o6 Y. P" q3 V4 N2 M q B: Y
+ n; O" C6 F$ o6 R- message MsgB {
9 [' a8 D/ |* a: U - field1: String;* r. T2 ?: J8 Y, b- N
- field2: String;) ~4 l7 [/ u4 \% n8 U6 C$ E1 ^3 F
- }
; |8 C* _- C6 y
- y K$ I! b. I& l) ~, f/ l- fun example() {' X2 Q" x# A) u _
- // Instance of a Struct StA
' E& Q& B p8 M. w. t - StA{
& a8 ?. g. m, l7 {% E# T9 A8 E - field1: 42,
/ l' G; G% t1 _6 x9 I* D - field2: 68 + 1, // trailing comma is allowed8 Z7 d" Q- C5 `4 ?# U
- };
' k' ^4 b9 d- z3 ?' I: G* g - + U: I9 I" h+ I% M1 R
- // Instance of a Message MsgB& W" w% K7 l- S
- MsgB{
. p4 M: g' C* n0 o8 l0 A - field1: "May the 4th",
* N P; |' b( }' W- K, W - field2: "be with you!", // trailing comma is allowed
7 R* }2 B0 J* m- R3 Y - };
3 v" r( g& K+ i* d6 |* m- A - }
复制代码- struct PopQuiz {
, `4 X! l7 T! y; p1 Y# U0 w - vogonsCount: Int;2 X; U4 I7 X% N9 T2 U5 N
- nicestNumber: Int;! W: A- b q/ O1 D4 c
- }
! z7 ?1 V4 g. F$ `) b
/ g7 y# b; ~; y# n- fun example() {
# E' ~5 E# ?& T j - // Let's introduce a couple of variables
' c4 v+ N. S1 W w" ]# Q# V - let vogonsCount: Int = 42;
- a" x! Y# u3 p, Q+ z- R$ i# M% ] U - let nicestNumber: Int = 68 + 1;
0 Q2 \ s, p! N1 T
8 Y* i+ P1 _# N8 }; A- // You may instantiate the Struct as usual and assign variables to fields,
3 D" S$ W8 @! p3 T# h; M* r; a6 q' G$ b - // but that is a bit repetitive and tedious at times
" L: L0 c q9 h) G8 z, L* m3 E - PopQuiz{ vogonsCount: vogonsCount, nicestNumber: nicestNumber };7 ~, q/ K( H1 Y M4 U9 r6 j% }/ A
+ U) i2 H) `3 f7 [! I% I+ @9 V- // Let's use field punning and type less,' ?. Z1 ?$ @. |* _. v
- // because our variable names happen to be the same as field names/ ^3 x2 a+ t1 [, j3 q9 X# j; Y- u3 @( v
- PopQuiz{
' O7 v# Y- p0 g! k7 a - vogonsCount,: T+ j2 q+ p& f8 J+ p& r1 h) v
- nicestNumber, // trailing comma is allowed here too!
% ]: ?! i( A7 H8 W, O! I0 `0 b - };9 i/ f; W7 @# l$ Z. R+ W) @, y0 N; V+ B
- }
复制代码- struct Big {0 m( F( _3 F3 H
- f1: Int; l7 t# Y v! y( y
- f2: Int;
) x9 Y' I1 f. O: x, v* C - f3: Int;3 ?1 l4 g0 ^; K7 X. h9 ^& f* Q5 A6 j
- f4: Int;
! l) @' m- w Y E, B' @ - f5: Int;, g( c6 B- d3 p- P2 N) k! W
- f6: Int;9 f& ?: C7 L; R |' Z
- }$ \) A, {4 O% R l# L
- $ L) n- Z( J) u: C
- fun conversionFun() {2 A* ]9 e3 l) J7 ?: @; ?$ Y
- dump(Big{
" \- Q( n6 _$ V9 X - f1: 10000000000, f2: 10000000000, f3: 10000000000,6 u v: q: n) g1 u1 p7 \ R4 {2 K
- f4: 10000000000, f5: 10000000000, f6: 10000000000,
# {: Y5 J& N5 M* \ - }.toCell()); // x{...cell with references...}
: X& }0 l% ^- N9 K H0 O - }
复制代码- struct Fizz { foo: Int }) k5 n! Z, N( ^* f- j/ B
- message(100) Buzz { bar: Int }0 f) {& m& f) A. I
- 8 u& P0 E( F# t$ m% s- k- z# A
- fun constructThenParse() {1 `5 L* |- j! y. a
- let fizzCell = Fizz{foo: 42}.toCell();
2 g9 k2 d1 I! `) a - let buzzCell = Buzz{bar: 27}.toCell();9 [3 J5 p" L/ U$ }+ V/ J) Y
+ `$ M7 C$ O5 l$ @( Y1 b, X- let parsedFizz: Fizz = Fizz.fromCell(fizzCell);/ b9 o7 H; o. c5 Q/ `
- let parsedBuzz: Buzz = Buzz.fromCell(buzzCell);* c) K6 R( [* L' i0 w
- }
复制代码- struct ArbitraryStruct {}0 o3 T. C" o N, C' _
- message(0x2A) ArbitraryMessage {}$ w% s2 f9 {" w6 V3 K
+ _. q, G. ]% r) a7 y7 y- fun lawOne() {4 N5 x& R0 @4 \" ~2 o
- let structInst = ArbitraryStruct{};/ n/ i0 R% Y& g; D! f
- let messageInst = ArbitraryMessage{}; r" ?/ |& ^, {, C
- 5 P4 |: G- s+ D( @6 ?( d% A
- ArbitraryStruct.fromCell(structInst.toCell()); // = structInst
: {4 v- I; ^9 ^+ J% M1 ~ - ArbitraryMessage.fromCell(messageInst.toCell()); // = messageInst
+ v" c) E2 x$ z& u, h( J - l/ Q) f/ c0 S+ C
- // Same goes for Slices, with .toCell().asSlice() and .fromSlice()
: u, C: T0 r/ j8 V; [# y' b. ^* H7 q - 6 \0 P0 @" W o# {/ p9 a b* x
- ArbitraryStruct.fromSlice(structInst.toCell().asSlice()); // = structInst g4 r8 K; ?1 l: H& F/ u2 j8 S: X& y6 a
- ArbitraryMessage.fromSlice(messageInst.toCell().asSlice()); // = messageInst
# k3 L1 ~1 I G, Z - }
复制代码 对于任何与给定 Struct/Message 具有相同 TL-B 布局的 cell,调用 Struct.fromCell()(或 Message.fromCell()),然后通过 .toCell() 将结果转换为 Cell,就会得到原始 cell 的副本:- struct ArbitraryStruct { val: Int as uint32 }
6 Z) m/ l3 y8 U - message(0x2A) ArbitraryMessage {}7 q( U' L/ L: Y
/ [: S# i6 }" g# s) O. o- fun lawTwo() {
- H, e, r9 f. i9 c - // Using 32 bits to store 42 just so this cellInst can be
8 [- ?8 K% H; J Z# P - // re-used for working with both ArbitraryStruct and ArbitraryMessage6 f3 x- o2 z3 k6 t
- let cellInst = beginCell().storeUint(42, 32).endCell();0 l( h8 i7 m6 @. F! H/ m
# P$ u5 R, l0 Z4 H* G- ArbitraryStruct.fromCell(cellInst).toCell(); // = cellInst* m2 d3 B: I6 l
- ArbitraryMessage.fromCell(cellInst).toCell(); // = cellInst' M% l% {2 x) P) x" m' x- V. E
- R4 _4 d' {' G7 C i( n- // Same goes for Slices, with .fromSlice() and .toCell().asSlice()
+ O' R/ [8 W1 K+ H7 e5 l - let sliceInst = cellInst.asSlice();
& l% Q6 N4 p6 i: P - . t! A* B4 B2 J J
- ArbitraryStruct.fromSlice(sliceInst).toCell().asSlice(); // = sliceInst
) b, F% s* t D8 y! V - ArbitraryMessage.fromSlice(sliceInst).toCell().asSlice(); // = sliceInst
# V; m8 ?- m) F6 _% C) L- m! N6 Y - }
复制代码
7 X) Q0 U& ]) v+ }, M Y |
|