1# Sendable使用规则与约束
2
3## Sendable class只能继承自Sendable class
4
5Sendable对象布局及原型链不可变,非Sendable对象可以通过特殊方式修改布局,不允许互相继承。这里的class不包括变量。Sendable class不能继承自变量。
6
7**正例:**
8
9```ts
10@Sendable
11class A {
12  constructor() {
13  }
14}
15
16@Sendable
17class B extends A {
18  constructor() {
19    super()
20  }
21}
22```
23
24**反例:**
25
26```ts
27class A {
28  constructor() {
29  }
30}
31
32@Sendable
33class B extends A {
34  constructor() {
35    super()
36  }
37}
38```
39
40
41## 非Sendable class只能继承自非Sendable class
42
43Sendable对象布局及原型链不可变,由于非Sendable对象可以通过特殊方式修改布局,因此不允许互相继承。
44
45**正例:**
46
47```ts
48class A {
49  constructor() {
50  }
51}
52
53class B extends A {
54  constructor() {
55    super()
56  }
57}
58```
59
60**反例:**
61
62```ts
63@Sendable
64class A {
65  constructor() {
66  }
67}
68
69class B extends A {
70  constructor() {
71    super()
72  }
73}
74```
75
76
77## 非Sendable class只能实现非Sendable interface
78
79如果非Sendable class实现了Sendable interface,可能会被认为是Sendable的,实际是非Sendable的,导致错误使用。
80
81**正例:**
82
83```ts
84interface I {};
85
86class B implements I {};
87```
88
89**反例:**
90
91```ts
92import { lang } from '@kit.ArkTS';
93
94type ISendable = lang.ISendable;
95
96interface I extends ISendable {};
97
98class B implements I {};
99```
100
101
102## Sendable class/interface成员变量必须是Sendable支持的数据类型
103
104Sendable数据不能持有非Sendable数据,因此Sendable数据的成员属性必须为Sendable数据。
105
106**正例:**
107
108```ts
109@Sendable
110class A {
111  constructor() {
112  }
113  a: number = 0;
114}
115```
116
117**反例:**
118
119```ts
120@Sendable
121class A {
122  constructor() {
123  }
124  b: Array<number> = [1, 2, 3] // 需使用collections.Array
125}
126```
127
128
129## Sendable class/interface的成员变量不支持使用!断言
130
131Sendable对象的成员属性必须赋初值,“!”修饰的变量可以不赋初值,因此不支持使用“!” 。
132
133**正例:**
134
135```ts
136@Sendable
137class A {
138  constructor() {
139  }
140  a: number = 0;
141}
142```
143
144**反例:**
145
146```ts
147@Sendable
148class A {
149  constructor() {
150  }
151  a!: number;
152}
153```
154
155
156## Sendable class/interface的成员变量不支持使用计算属性名
157
158Sendable对象的布局不可变,计算属性不能静态确定对象布局,因此不支持。
159
160**正例:**
161
162```ts
163@Sendable
164class A {
165    num1: number = 1;
166    num2: number = 2;
167    add(): number {
168      return this.num1 + this.num2;
169    }
170}
171```
172
173**反例:**
174
175```ts
176enum B {
177    b1 = "bbb"
178}
179@Sendable
180class A {
181    ["aaa"]: number = 1; // ["aaa"] is allowed in other classes in ets files
182    [B.b1]: number = 2; // [B.b1] is allowed in other classes in ets files
183}
184```
185
186
187## 泛型类中的Sendable class,collections.Arraycollections.Mapcollections.Set的模板类型必须是Sendable类型
188
189Sendable数据不能持有非Sendable数据,因此泛型类中的Sendable数据的模版类型必须是Sendable类型。
190
191**正例:**
192
193```ts
194import { collections } from '@kit.ArkTS';
195
196try {
197  let arr1: collections.Array<number> = new collections.Array<number>();
198  let num: number = 1;
199  arr1.push(num);
200} catch (e) {
201  console.error(`taskpool execute: Code: ${e.code}, message: ${e.message}`);
202}
203```
204
205**反例:**
206
207```ts
208import { collections } from '@kit.ArkTS';
209
210try {
211  let arr1: collections.Array<Array<number>> = new collections.Array<Array<number>>();
212  let arr2: Array<number> = new Array<number>();
213  arr2.push(1);
214  arr1.push(arr2);
215} catch (e) {
216  console.error(`taskpool execute: Code: ${e.code}, message: ${e.message}`);
217}
218```
219
220
221## Sendable class的内部不允许使用当前模块内上下文环境中定义的变量
222
223由于Sendable对象在不同并发实例间的上下文环境不同,属于单个虚拟机实例,如果直接访问会有非预期行为。不支持Sendable对象使用当前模块内上下文环境中定义的变量,如果违反,编译阶段会报错。
224
225> **说明:**
226>
227> 从API version 12开始,sendable class的内部支持使用top level的sendable class对象。
228
229**正例:**
230
231```ts
232import { lang } from '@kit.ArkTS';
233
234type ISendable = lang.ISendable;
235
236interface I extends ISendable {}
237
238@Sendable
239class B implements I {
240  static o: number = 1;
241  static bar(): B {
242    return new B();
243  }
244}
245
246@Sendable
247class C {
248  v: I = new B();
249  u: number = B.o;
250
251  foo() {
252    return B.bar();
253  }
254}
255```
256
257**反例:**
258
259```ts
260import { lang } from '@kit.ArkTS';
261
262type ISendable = lang.ISendable;
263
264interface I extends ISendable {}
265
266@Sendable
267class B implements I {}
268
269function bar(): B {
270  return new B();
271}
272
273let b = new B();
274
275{
276  @Sendable
277  class A implements I {}
278
279  @Sendable
280  class C {
281    u: I = bar(); // bar不是sendable class对象,编译报错
282    v: I = new A(); // A不是定义在top level中,编译报错
283
284    foo() {
285      return b; // b不是sendable class对象,而是sendable class的实例,编译报错
286    }
287  }
288}
289```
290
291
292## Sendable class和Sendable function不能使用除了\@Sendable的其它装饰器
293
294如果类装饰器定义在ts文件中,产生修改类的布局的行为,那么会造成运行时的错误。
295
296**正例:**
297
298```ts
299@Sendable
300class A {
301  num: number = 1;
302}
303```
304
305**反例:**
306
307```ts
308@Sendable
309@Observed
310class C {
311  num: number = 1;
312}
313```
314
315
316## 不能使用对象字面量/数组字面量初始化Sendable类型
317
318对象字面量/数组字面量是非Sendable类型,Sendable数据类型只能通过Sendable类型的new表达式创建。
319
320**正例:**
321
322```ts
323import { collections } from '@kit.ArkTS';
324
325let arr1: collections.Array<number> = new collections.Array<number>(1, 2, 3); // 是Sendable类型
326```
327
328**反例:**
329
330```ts
331import { collections } from '@kit.ArkTS';
332
333let arr2: collections.Array<number> = [1, 2, 3]; // 不是Sendable类型,编译报错
334let arr3: number[] = [1, 2, 3]; // 不是Sendable类型,正例,不报错
335let arr4: number[] = new collections.Array<number>(1, 2, 3); // 编译报错
336```
337
338
339## 非Sendable类型不可以as成Sendable类型
340
341除了Object类型,非Sendable类型不可以as成Sendable类型。非Sendable类型通过as强转成Sendable类型后实际是非Sendable的类型数据,会导致错误使用。Sendable类型在不违反Sendable规则的前提下需要和非Sendable类型行为兼容,因此Sendable类型可以as成非Sendable类型。
342
343**正例:**
344
345```ts
346class A {
347  state: number = 0;
348}
349
350@Sendable
351class SendableA {
352  state: number = 0;
353}
354
355let a1: A = new SendableA() as A;
356```
357
358**反例:**
359
360```ts
361class A {
362  state: number = 0;
363}
364
365@Sendable
366class SendableA {
367  state: number = 0;
368}
369
370let a2: SendableA = new A() as SendableA;
371```
372
373
374## 箭头函数不支持共享
375
376箭头函数不支持使用Sendable装饰器,是非Sendable函数,因此不支持共享。
377
378**正例:**
379
380```ts
381@Sendable
382type SendableFuncType = () => void;
383
384@Sendable
385function SendableFunc() {
386  console.info("Sendable func");
387}
388
389@Sendable
390class SendableClass {
391  constructor(f: SendableFuncType) {
392    this.func = f;
393  }
394  func: SendableFuncType;
395}
396
397let sendableClass = new SendableClass(SendableFunc);
398```
399
400**反例:**
401
402```ts
403@Sendable
404type SendableFuncType = () => void;
405let func: SendableFuncType = () => {}; // 编译报错
406
407@Sendable
408class SendableClass {
409  func: SendableFuncType = () => {}; // 编译报错
410}
411```
412
413
414## Sendable装饰器修饰类型时仅支持修饰函数类型
415
416当前仅支持声明Sendable函数类型,因此只能修饰函数类型。
417
418**正例:**
419
420```ts
421@Sendable
422type SendableFuncType = () => void;
423```
424
425**反例:**
426
427```ts
428@Sendable
429type A = number; // 编译报错
430
431@Sendable
432class C {}
433
434@Sendable
435type D = C; // 编译报错
436```
437
438
439## 注意事项
440
441
442在HAR中使用Sendable时,需开启编译生成TS文件的配置。详情可查[编译生成TS文件](../quick-start/har-package.md#编译生成ts文件)。
443
444
445## 与TS/JS交互的规则
446
447
448### ArkTS通用规则(目前只针对Sendable对象)
449
450| 规则 |
451| -------- |
452| Sendable对象传入TS/JS的接口中,禁止操作其对象布局(增、删属性,改变属性类型)。 |
453| Sendable对象设置到TS/JS的对象上,TS中获取到这个Sendable对象后,禁止操作其对象布局(增、删属性,改变属性类型)。 |
454| Sendable对象放入TS/JS的容器中,TS中获取到这个Sendable对象后,禁止操作其对象布局(增、删属性,改变属性类型)。 |
455
456> **说明:**
457>
458> 此处改变属性类型不包括Sendable对象类型的改变,比如从Sendable class A 变为Sendable class B。
459
460
461### NAPI规则(目前只针对Sendable对象)
462
463| 规则 |
464| -------- |
465| 禁止删除属性,不能使用的接口有:napi_delete_property。 |
466| 禁止新增属性,不能使用的接口有:napi_set_property、napi_set_named_property、napi_define_properties。 |
467| 禁止修改属性类型,不能使用的接口有:napi_set_property、napi_set_named_property、napi_define_properties。 |
468| 不支持Symbol相关接口和类型,不能使用的接口有:napi_create_symbol、napi_is_symbol_object、napi_symbol。 |
469
470
471## 与UI交互的规则
472
473Sendable数据需要与[makeObserved](../quick-start/arkts-new-makeObserved.md)联用,才可以观察Sendable对象的数据变化,具体使用请参考[makeObserved和@Sendable装饰的class配合文档](../quick-start/arkts-new-makeObserved.md#makeobserved和sendable装饰的class配合使用)。
474