从API version 12开始,Sendable class的内部支持使用top level的Sendable class对象。
Sendable对象的布局和原型链不可变,而非Sendable对象可以通过特殊方式修改布局。因此,不允许互相继承。此处的继承规则针对类定义本身,不涉及类的实例变量。Sendable类只能继承自Sendable类的定义。
正例:
// 正例:
@Sendable
class A {
constructor() {
console.info('hello world');
}
}
@Sendable
class B extends A {
constructor() {
super()
}
}反例:
class A {
constructor() {
}
}
@Sendable
class B extends A { // A不是sendable class,B不能继承它,编译报错
constructor() {
super()
}
} Sendable对象的布局和原型链不可变,而非Sendable对象可以通过特殊方式修改布局,因此不允许互相继承。
正例:
// 正例:
class A {
constructor() {
console.info('hello world');
}
}
class B extends A {
constructor() {
console.info('HELLO WORLD');
super()
}
}反例:
@Sendable
class A {
constructor() {
}
}
class B extends A { // A是sendable class,B不能继承它,编译报错
constructor() {
super()
}
} 非Sendable类实现Sendable接口时,可能被误认为是Sendable类,导致错误使用。
正例:
// 正例:
interface I {
a: string;
};
class B implements I {
a: string = 'hello world';
};反例:
import { lang } from '@kit.ArkTS';
type ISendable = lang.ISendable;
interface I extends ISendable {};
class B implements I {}; // I是sendable interface,B不能实现,编译报错 Sendable数据不得持有非Sendable数据,因此Sendable类或接口的成员变量必须是Sendable支持的数据类型。
正例:
// 正例:
@Sendable
class A {
constructor() {
}
a: number = 0;
}反例:
@Sendable
class A {
constructor() {
}
b: Array<number> = [1, 2, 3] // 编译报错,需使用collections.Array
} Sendable对象的成员属性必须赋初值,而“!”修饰的变量可以不赋初值,因此不支持使用“!”。
正例:
// 正例:
@Sendable
class A {
constructor() {
}
a: number = 0;
}反例:
@Sendable
class A {
constructor() {
}
a!: number; // 编译报错,不支持使用“!”
} Sendable对象的布局不可更改,因为计算属性无法静态确定对象布局,所以不支持。
正例:
// 正例:
@Sendable
class A {
num1: number = 1;
num2: number = 2;
add(): number {
return this.num1 + this.num2;
}
}反例:
enum B {
b1 = 'bbb'
}
@Sendable
class A {
['aaa']: number = 1; // 编译报错,不支持['aaa']
[B.b1]: number = 2; // 编译报错,不支持[B.b1]
} Sendable类的成员变量不能使用类型别名(即使用type关键字定义的别名)。
正例:
@Sendable
class B {
num1: number = 1;
num2: number = 2;
add(): number {
return this.num1 + this.num2;
}
} 反例:
type A = number;
@Sendable
class B {
num1: A = 1; // 运行报错,不支持使用类型别名
num2: A = 2; // 运行报错,不支持使用类型别名
add(): number {
return this.num1 + this.num2;
}
} Sendable数据不能持有非Sendable数据,因此泛型类中的Sendable数据的模板类型必须是Sendable类型。
正例:
import { collections } from '@kit.ArkTS';
try {
let arr: collections.Array<number> = new collections.Array<number>();
let num: number = 1;
arr.push(num);
} catch (e) {
console.error(`create collections error: Code: ${e.code}, message: ${e.message}`);
}反例:
import { collections } from '@kit.ArkTS';
try {
let arr1: collections.Array<Array<number>> = new collections.Array<Array<number>>(); // 编译报错,模板类型必须是Sendable类型
let arr2: Array<number> = new Array<number>();
arr2.push(1);
arr1.push(arr2);
} catch (e) {
console.error(`create collections error: Code: ${e.code}, message: ${e.message}`);
} 由于Sendable对象在不同并发实例间的上下文环境不同,属于单个虚拟机实例,如果直接访问会有非预期行为。不支持Sendable对象使用当前模块内上下文环境中定义的变量,违反此规则会在编译阶段报错。
从API version 12开始,Sendable class的内部支持使用top level的Sendable class对象。
正例:
// 正例:
import { lang } from '@kit.ArkTS';
type ISendable = lang.ISendable;
interface I extends ISendable {}
@Sendable
class B implements I {
static o: number = 1;
static bar(): B {
return new B();
}
}
@Sendable
class C {
v: I = new B();
u: number = B.o;
foo() {
return B.bar();
}
}反例:
import { lang } from '@kit.ArkTS';
type ISendable = lang.ISendable;
interface I extends ISendable {}
@Sendable
class B implements I {}
function bar(): B {
return new B();
}
let b = new B();
{
@Sendable
class A implements I {}
@Sendable
class C {
u: I = bar(); // bar不是sendable function对象,编译报错
v: I = new A(); // A不是定义在top level中,编译报错
foo() {
return b; // b不是sendable class对象,而是sendable class的实例,编译报错
}
}
} 当前仅支持修饰类和函数。
正例:
// 正例: @Sendable type SendableFuncType = () => void;
反例:
@Sendable
type A = number; // 编译报错
@Sendable
class C {}
@Sendable
type D = C; // 编译报错 在ts文件中定义类装饰器时,可能会改变类的结构,进而引发运行时错误。
正例:
// 正例:
@Sendable
class A {
num: number = 1;
}反例:
@Sendable
@Observed // 编译报错
class C {
num: number = 1;
} 从API version 22开始,支持在Sendable class上叠加使用除@Sendable装饰器之外的其他自定义装饰器。
通过在工程级build-profile.json5文件的"buildOption"字段下的"strictMode"中增加"disableSendableCheckRules"字段,配置该能力。
"disableSendableCheckRules"字段及其具体取值示例如下:
"buildOption": {
"strictMode": {
"caseSensitiveCheck": true,
"useNormalizedOHMUrl": true,
"disableSendableCheckRules": ["arkts-sendable-class-decorator"]
}
} "disableSendableCheckRules"字段值为包含Sendable规则的数组。
默认不展示,即默认不支持在Sendable class上叠加使用除@Sendable之外的其他自定义装饰器。
禁止配置为空数组。
当数组中配置了"arkts-sendable-class-decorator"规则时,支持在Sendable class上叠加除@Sendable之外的其他自定义装饰器。
@Sendable和其他自定义装饰器叠加使用可能造成运行时异常,需要开发者适配装饰器函数的实现。
对象字面量和数组字面量不是Sendable类型。Sendable类型必须通过Sendable类型的new表达式创建。
正例:
// 正例:
import { collections } from '@kit.ArkTS';
let arr1: collections.Array<number> = new collections.Array<number>(1, 2, 3); // 是Sendable类型反例:
import { collections } from '@kit.ArkTS';
let arr2: collections.Array<number> = [1, 2, 3]; // 不是Sendable类型,编译报错
let arr3: number[] = [1, 2, 3]; // 不是Sendable类型,正例,不报错
let arr4: number[] = new collections.Array<number>(1, 2, 3); // 编译报错 除了Object类型,非Sendable类型不能强转成Sendable类型。非Sendable类型通过as强转成Sendable类型后,实际数据仍为非Sendable类型,会导致错误使用。Sendable类型在不违反Sendable规则的前提下,需要和非Sendable类型行为兼容,因此Sendable类型可以通过as强转成非Sendable类型。
正例:
// 正例:
class A {
state: number = 0;
}
@Sendable
class SendableA {
state: number = 0;
}
let a1: A = new SendableA() as A;反例:
class A {
state: number = 0;
}
@Sendable
class SendableA {
state: number = 0;
}
let a2: SendableA = new A() as SendableA; // 编译报错 反例:
@Sendable
type SendableFuncType = () => void;
let func: SendableFuncType = () => {}; // 编译报错
@Sendable
class SendableClass {
func: SendableFuncType = () => {}; // 编译报错
} | 规则 |
|---|
| Sendable对象传入TS/JS的接口中,禁止操作其对象布局(增、删属性,改变属性类型)。 |
| Sendable对象设置到TS/JS的对象上,TS中获取到Sendable对象后,禁止操作其对象布局(增、删属性,改变属性类型)。 |
| Sendable对象放入TS/JS的容器中,TS中获取到Sendable对象后,禁止操作其对象布局(增、删属性,改变属性类型)。 |
改变属性类型不包括Sendable对象类型的改变,例如从Sendable class A变为Sendable class B。
NAPI相关接口请参考Sendable相关的NAPI接口,具体使用请参考Native与Sendable ArkTS对象绑定。
| 规则 |
|---|
| 禁止删除属性。不能使用napi_delete_property接口。 |
| 禁止新增属性。不能使用napi_set_property、napi_set_named_property、napi_define_properties接口。 |
| 禁止修改属性类型。不能使用napi_set_property、napi_set_named_property、napi_define_properties接口。 |
| 不支持Symbol相关接口和类型。不能使用napi_create_symbol、napi_is_symbol_object、napi_symbol接口。 |
Sendable数据需要与makeObserved配合使用,才可以观察Sendable对象的数据变化,具体使用请参考makeObserved和@Sendable装饰的class配合文档。
Sendable可在HAR包中使用。当在字节码HAR中使用Sendable时,无需进行额外配置,可直接使用。当在TS HAR中使用Sendable时,需在HAR模块下的module.json5文件中将"metadata"字段下的"name"设置为“UseTsHar”,配置如下所示。
{
"module": {
"name": "library",
"type": "har",
"deviceTypes": [
"tablet",
"2in1"
],
"metadata": [
{
"name": "UseTsHar",
"value": "true"
}
]
}
}