Appearance
ArkTS 数据结构
struct vs class 的深层理解、Sendable 对象机制、ArkTS 中的集合类型。
1. struct(结构体)在 ArkTS 中的角色
1.1 struct 的用途
在 ArkTS 中,struct 有两个核心用途:
- UI 组件定义(配合 @Component 装饰器)
- 纯数据容器(类似 DTO/POJO)
1.2 UI 组件 struct
typescript
@Component
struct UserInfo {
@State name: string = '未知'
@State age: number = 0
@State avatar: Resource = $r('app.media.default_avatar')
build() {
Row() {
Image(this.avatar)
.width(48)
.height(48)
.borderRadius(24)
Column() {
Text(this.name)
.fontSize(16)
.fontWeight(FontWeight.Bold)
Text(`${this.age}岁`)
.fontSize(14)
.fontColor(Color.Gray)
}
.margin({ left: 12 })
}
.width('100%')
.padding(12)
}
}1.3 数据容器 struct
typescript
// 纯数据容器,不需要 @Component
struct Point {
x: number
y: number
}
struct Size {
width: number
height: number
}
struct Rect {
top: number
left: number
width: number
height: number
}
// 使用
const rect: Rect = { top: 0, left: 0, width: 100, height: 200 }2. struct vs class 对比
| 维度 | struct | class |
|---|---|---|
| 用途 | UI 组件、数据容器 | 逻辑类、业务逻辑 |
| 继承 | ❌ 不可继承 | ✅ 可继承 |
| 装饰器 | @Component(组件必选) | 无强制要求 |
| 必须实现 | build() 函数 | 无 |
| 实例化 | new MyStruct() | new MyClass() |
| 状态管理 | 可用 @State/@Prop 等 | 普通类属性 |
| 编译优化 | AOT 编译 | AOT 编译 |
| 内存开销 | 更低(编译器优化) | 略高 |
决策流程图
需要创建 UI 组件?
├─ 是 → struct + @Component
└─ 否
├─ 需要继承? → class
├─ 需要状态管理? → struct
└─ 其他 → class(更灵活)3. Sendable 对象
3.1 什么是 Sendable?
Sendable 是 ArkTS 中用于线程间传递的特殊对象类型。它实现了 ISendable 接口,可以在 Actor 模型的线程间通过引用高效传递,而无需序列化。
typescript
interface ISendable {
__isSendable__: true
readonly id: string
}
// 实现 Sendable 接口的类
class Message implements ISendable {
__isSendable__: true = true
readonly id: string
readonly content: string
readonly timestamp: number
constructor(content: string) {
this.id = `msg_${Date.now()}_${Math.random().toString(36).slice(2)}`
this.content = content
this.timestamp = Date.now()
}
}
// 线程间传递(无需序列化)
async function sendMessage() {
const msg = new Message('Hello')
await TaskPool.execute(() => {
// 子线程中直接访问
console.log(msg.content) // 高效传递
})
}3.2 Sendable 的规则
- 只能包含基本类型和 Sendable 字段
- 字段必须是 readonly(不可变)
- 不能包含非 Sendable 对象引用
- 不能包含闭包/函数引用
4. 集合类型
4.1 Array
typescript
// 创建数组
let arr: number[] = [1, 2, 3]
let arr2: Array<string> = ['a', 'b', 'c']
// 常用方法
arr.push(4) // 追加
arr.pop() // 弹出最后一个
arr.shift() // 弹出第一个
arr.unshift(0) // 头部追加
arr.splice(1, 1) // 删除索引1的元素
arr.indexOf(2) // 查找索引
arr.includes(2) // 是否包含
// 迭代
arr.forEach((item, index) => {
console.log(index, item)
})
// 映射
const doubled = arr.map(x => x * 2)
// 过滤
const evens = arr.filter(x => x % 2 === 0)
// 查找
const found = arr.find(x => x > 2)
// 排序
arr.sort((a, b) => a - b) // 升序
arr.reverse() // 反转4.2 Map
typescript
// Map:键值对集合,键可以是任意类型
let userMap = new Map<string, User>()
userMap.set('user1', { id: 1, name: '小明' })
userMap.set('user2', { id: 2, name: '小红' })
console.log(userMap.get('user1')) // 获取
console.log(userMap.has('user1')) // 检查
console.log(userMap.size) // 大小
userMap.delete('user1') // 删除
// 遍历
for (const [key, value] of userMap) {
console.log(key, value.name)
}4.3 Set
typescript
// Set:唯一值集合
let tags = new Set<string>()
tags.add('鸿蒙')
tags.add('ArkTS')
tags.add('鸿蒙') // 重复,不会添加
console.log(tags.has('鸿蒙')) // true
console.log(tags.size) // 2
// 遍历
for (const tag of tags) {
console.log(tag)
}5. ArkTS 中的对象类型
5.1 Object 与 Record
typescript
// 普通对象(类型较宽泛)
let obj: object = { name: '小明' }
// Record 对象(类型精确)
let dict: Record<string, number> = {
'a': 1,
'b': 2
}
// 对比性能:Record 的 Hidden Class 优化更好
type UserDict = Record<string, User>
const users: UserDict = {}5.2 深拷贝 vs 浅拷贝
typescript
// 浅拷贝(推荐用展开运算符)
let original = { name: '小明', address: { city: '北京' } }
let shallow = { ...original }
shallow.address.city = '上海'
console.log(original.address.city) // '上海'(浅拷贝!)
// 深拷贝(需要递归实现)
function deepClone<T>(obj: T): T {
return JSON.parse(JSON.stringify(obj))
}
let deep = deepClone(original)
deep.address.city = '上海'
console.log(original.address.city) // '北京'(深拷贝!)💡 面试考点:ArkTS 中推荐使用深拷贝 + 赋值来修改数组/对象,避免直接引用修改导致的数据一致性问题。
6. 面试高频考点
Q1: struct 和 class 在 ArkTS 中的区别?
回答:UI 组件用 struct(不可继承,必须有 build());纯逻辑类用 class(可继承,更灵活)。struct 编译优化更好,class 支持继承和更完整的 OOP 特性。
Q2: Sendable 对象的作用?
回答:在 Actor 模型的线程间传递对象时,实现 Sendable 接口可避免序列化,通过引用高效传递。要求字段 readonly、只包含基本类型和 Sendable 字段。
Q3: ArkTS 中深拷贝的推荐方式?
回答:JSON.parse(JSON.stringify(obj)) 是最常用的深拷贝方式。在状态变更时应该用深拷贝+赋值,而非直接修改引用。
🐱 小猫提示:数据结构部分记住两个核心对比:struct vs class 的适用场景区分,以及深拷贝 vs 浅拷贝的使用场景。