鸿蒙学习实战之路:ArkTS基础接口与类定义
ArkTS基础接口与类定义
文章概述
本文是ArkTS语言的基础教程,重点讲解在HarmonyOS应用开发中如何使用ArkTS定义类、接口以及相关的面向对象编程概念。通过本文,您将掌握ArkTS的核心语法特性,为构建复杂的HarmonyOS应用打下坚实基础。
官方参考资料:
基础概念
什么是ArkTS?
ArkTS是HarmonyOS优选的应用开发语言,它在TypeScript的基础上,扩展了声明式UI、状态管理等能力。
主要特性:
- 静态类型检查
- 面向对象编程支持
- 声明式UI描述
- 状态驱动UI更新
- 与HarmonyOS API深度集成
环境要求
开发环境配置:
- DevEco Studio 4.0或更高版本
- HarmonyOS SDK API 9或更高版本
- 推荐使用Node.js 16.x或18.x
类定义基础
基本类定义
在ArkTS中,使用class关键字定义类,类可以包含属性、构造器和方法。
// 基础类定义示例
class Person {
// 类属性
name: string
age: number
// 构造器
constructor(name: string, age: number) {
this.name = name
this.age = age
}
// 类方法
introduce(): string {
return `大家好,我是${this.name},今年${this.age}岁。`
}
// 带参数的方法
celebrateBirthday(): void {
this.age++
console.log(`${this.name}过生日啦!现在${this.age}岁。`)
}
}
// 使用示例
@Entry
@Component
struct ClassExample {
build() {
Column() {
Button('创建Person实例')
.onClick(() => {
let person = new Person('张三', 25)
console.log(person.introduce())
person.celebrateBirthday()
})
}
.width('100%')
.height('100%')
.padding(20)
}
}
构造器参数属性
ArkTS支持在构造器参数中直接定义属性,这是定义类的简洁方式。
// 使用构造器参数属性
class Student {
// 直接在构造器参数中定义属性
constructor(
public name: string,
public studentId: string,
private grade: number = 1 // 默认参数
) {}
getStudentInfo(): string {
return `学生:${this.name},学号:${this.studentId},年级:${this.grade}`
}
promote(): void {
this.grade++
console.log(`${this.name}升到${this.grade}年级`)
}
}
// 使用示例
@Entry
@Component
struct StudentExample {
build() {
Column() {
Button('创建学生')
.onClick(() => {
let student = new Student('李四', '2024001')
console.log(student.getStudentInfo())
student.promote()
})
}
.width('100%')
.height('100%')
}
}
接口定义与应用
基础接口定义
接口用于定义对象的形状,确保类实现特定的结构。
// 定义接口
interface Animal {
name: string
age: number
makeSound(): void
move(): void
}
// 实现接口的类
class Dog implements Animal {
name: string
age: number
breed: string
constructor(name: string, age: number, breed: string) {
this.name = name
this.age = age
this.breed = breed
}
makeSound(): void {
console.log(`${this.name}在汪汪叫!`)
}
move(): void {
console.log(`${this.name}在奔跑`)
}
// 类特有的方法
fetch(): void {
console.log(`${this.name}在接飞盘`)
}
}
class Cat implements Animal {
name: string
age: number
color: string
constructor(name: string, age: number, color: string) {
this.name = name
this.age = age
this.color = color
}
makeSound(): void {
console.log(`${this.name}在喵喵叫!`)
}
move(): void {
console.log(`${this.name}在优雅地走路`)
}
climbTree(): void {
console.log(`${this.name}在爬树`)
}
}
可选属性和只读属性
接口支持可选属性和只读属性,提供更灵活的类型定义。
// 包含可选和只读属性的接口
interface Vehicle {
readonly id: string // 只读属性
brand: string
model: string
year?: number // 可选属性
start(): void
stop(): void
}
class Car implements Vehicle {
readonly id: string
brand: string
model: string
year?: number
constructor(id: string, brand: string, model: string, year?: number) {
this.id = id
this.brand = brand
this.model = model
this.year = year
}
start(): void {
console.log(`${this.brand} ${this.model} 启动`)
}
stop(): void {
console.log(`${this.brand} ${this.model} 停止`)
}
// 尝试修改只读属性会报错
// updateId(newId: string): void {
// this.id = newId // 编译错误:无法分配到"id",因为它是只读属性
// }
}
继承与多态
类继承
ArkTS支持类的单继承,使用extends关键字。
// 基类
class Shape {
color: string
protected position: { x: number, y: number } // 受保护属性
constructor(color: string, x: number = 0, y: number = 0) {
this.color = color
this.position = { x, y }
}
// 基础方法
move(x: number, y: number): void {
this.position.x = x
this.position.y = y
console.log(`图形移动到位置 (${x}, ${y})`)
}
// 抽象方法(在TypeScript中需要使用abstract关键字,但ArkTS基于TS)
getArea(): number {
return 0
}
describe(): string {
return `这是一个${this.color}的图形`
}
}
// 派生类
class Circle extends Shape {
radius: number
constructor(color: string, radius: number, x: number = 0, y: number = 0) {
super(color, x, y) // 调用父类构造器
this.radius = radius
}
// 重写父类方法
getArea(): number {
return Math.PI * this.radius * this.radius
}
describe(): string {
return `${super.describe()},是一个半径为${this.radius}的圆形,面积:${this.getArea().toFixed(2)}`
}
// 子类特有方法
getCircumference(): number {
return 2 * Math.PI * this.radius
}
}
class Rectangle extends Shape {
width: number
height: number
constructor(color: string, width: number, height: number, x: number = 0, y: number = 0) {
super(color, x, y)
this.width = width
this.height = height
}
getArea(): number {
return this.width * this.height
}
describe(): string {
return `${super.describe()},是一个${this.width}x${this.height}的矩形,面积:${this.getArea()}`
}
// 子类特有方法
isSquare(): boolean {
return this.width === this.height
}
}
多态应用
@Entry
@Component
struct ShapeExample {
build() {
Column() {
Button('多态演示')
.onClick(() => {
// 多态:父类引用指向子类对象
let shapes: Shape[] = [
new Circle('红色', 5),
new Rectangle('蓝色', 4, 6),
new Circle('绿色', 3)
]
shapes.forEach(shape => {
console.log(shape.describe())
})
})
}
.width('100%')
.height('100%')
.padding(20)
}
}
访问控制修饰符
ArkTS提供了三种访问控制修饰符,用于控制类成员的可见性。
| 修饰符 | 类内部 | 子类 | 类外部 | 描述 |
|---|---|---|---|---|
public |
✅ | ✅ | ✅ | 默认修饰符,任何地方都可访问 |
private |
✅ | ❌ | ❌ | 仅在类内部可访问 |
protected |
✅ | ✅ | ❌ | 类内部和子类可访问 |
class BankAccount {
public readonly accountNumber: string
private _balance: number = 0
protected owner: string
constructor(accountNumber: string, owner: string, initialBalance: number = 0) {
this.accountNumber = accountNumber
this.owner = owner
this._balance = initialBalance
}
// 公共方法 - 可以外部调用
public deposit(amount: number): void {
if (amount > 0) {
this._balance += amount
console.log(`存入${amount}元,当前余额:${this._balance}元`)
}
}
public withdraw(amount: number): boolean {
if (amount > 0 && this._balance >= amount) {
this._balance -= amount
console.log(`取出${amount}元,当前余额:${this._balance}元`)
return true
}
console.log('取款失败:余额不足或金额无效')
return false
}
// 私有方法 - 只能在类内部使用
private validateAmount(amount: number): boolean {
return amount > 0 && amount <= 1000000
}
// 受保护方法 - 子类可以访问
protected updateOwner(newOwner: string): void {
this.owner = newOwner
console.log(`账户持有人变更为:${newOwner}`)
}
// 公开的getter方法
public get balance(): number {
return this._balance
}
}
// 继承示例
class SavingsAccount extends BankAccount {
private interestRate: number
constructor(accountNumber: string, owner: string, interestRate: number) {
super(accountNumber, owner)
this.interestRate = interestRate
}
// 可以访问父类的protected成员
transferOwnership(newOwner: string): void {
this.updateOwner(newOwner) // 可以调用protected方法
}
// 无法访问父类的private成员
// showPrivateBalance(): void {
// console.log(this._balance) // 编译错误:_balance是私有的
// }
addInterest(): void {
const interest = this.balance * this.interestRate // 通过public getter访问
this.deposit(interest)
console.log(`添加利息:${interest.toFixed(2)}元`)
}
}
@Entry
@Component
struct BankExample {
build() {
Column() {
Button('银行账户演示')
.onClick(() => {
let account = new SavingsAccount('123456789', '王五', 0.05)
account.deposit(1000)
account.addInterest()
console.log(`当前余额:${account.balance}元`)
// 以下操作会报错:
// account._balance = 9999 // 错误:_balance是私有的
// account.updateOwner('赵六') // 错误:updateOwner是受保护的
})
}
.width('100%')
.height('100%')
.padding(20)
}
}
静态成员
静态成员属于类本身,而不是类的实例。
class MathUtils {
// 静态属性
static readonly PI: number = 3.14159
static readonly VERSION: string = '1.0.0'
// 静态方法
static calculateCircleArea(radius: number): number {
return this.PI * radius * radius
}
static calculateDistance(x1: number, y1: number, x2: number, y2: number): number {
return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2))
}
static getVersion(): string {
return `数学工具库版本:${this.VERSION}`
}
}
class Counter {
private static instanceCount: number = 0
private static _totalCount: number = 0
public readonly id: number
constructor() {
Counter.instanceCount++
this.id = Counter.instanceCount
}
// 静态getter
static get totalInstances(): number {
return this.instanceCount
}
static get totalCount(): number {
return this._totalCount
}
increment(): void {
Counter._totalCount++
console.log(`计数器${this.id}增加,总计:${Counter._totalCount}`)
}
decrement(): void {
if (Counter._totalCount > 0) {
Counter._totalCount--
console.log(`计数器${this.id}减少,总计:${Counter._totalCount}`)
}
}
}
@Entry
@Component
struct StaticExample {
build() {
Column() {
Button('静态成员演示')
.onClick(() => {
// 使用静态方法,不需要创建实例
console.log(`PI值:${MathUtils.PI}`)
console.log(`半径为5的圆面积:${MathUtils.calculateCircleArea(5).toFixed(2)}`)
console.log(MathUtils.getVersion())
// 计数器实例演示
let counter1 = new Counter()
let counter2 = new Counter()
counter1.increment()
counter2.increment()
counter1.increment()
counter1.decrement()
console.log(`创建的计数器实例数:${Counter.totalInstances}`)
console.log(`总计数值:${Counter.totalCount}`)
})
}
.width('100%')
.height('100%')
.padding(20)
}
}
抽象类和接口的高级用法
抽象类
抽象类不能实例化,只能被继承,可以包含抽象方法和具体实现。
// 抽象类
abstract class Notification {
protected recipient: string
protected message: string
constructor(recipient: string, message: string) {
this.recipient = recipient
this.message = message
}
// 抽象方法 - 必须由子类实现
abstract send(): boolean
// 具体方法 - 子类可以继承使用
protected formatMessage(): string {
return `给 ${this.recipient} 的消息:${this.message}`
}
// 模板方法模式
processNotification(): void {
console.log('开始处理通知...')
const success = this.send()
if (success) {
console.log('通知发送成功')
this.logNotification()
} else {
console.log('通知发送失败')
}
}
private logNotification(): void {
console.log(`通知记录:${new Date().toISOString()} - ${this.formatMessage()}`)
}
}
// 具体实现类
class EmailNotification extends Notification {
private emailAddress: string
constructor(recipient: string, message: string, emailAddress: string) {
super(recipient, message)
this.emailAddress = emailAddress
}
send(): boolean {
console.log(`发送邮件到:${this.emailAddress}`)
console.log(`邮件内容:${this.formatMessage()}`)
// 模拟发送逻辑
return Math.random() > 0.2 // 80%成功率
}
}
class SMSNotification extends Notification {
private phoneNumber: string
constructor(recipient: string, message: string, phoneNumber: string) {
super(recipient, message)
this.phoneNumber = phoneNumber
}
send(): boolean {
console.log(`发送短信到:${this.phoneNumber}`)
console.log(`短信内容:${this.message}`) // 短信通常较短,不使用完整格式
// 模拟发送逻辑
return Math.random() > 0.3 // 70%成功率
}
}
接口继承
接口可以继承其他接口,实现接口的组合。
// 基础接口
interface Identifiable {
readonly id: string
createdAt: Date
}
interface Timestampable {
updatedAt: Date
updateTimestamp(): void
}
// 接口继承
interface User extends Identifiable, Timestampable {
username: string
email: string
isActive: boolean
activate(): void
deactivate(): void
}
// 实现复合接口
class SystemUser implements User {
readonly id: string
createdAt: Date
updatedAt: Date
username: string
email: string
isActive: boolean = true
constructor(id: string, username: string, email: string) {
this.id = id
this.username = username
this.email = email
this.createdAt = new Date()
this.updatedAt = new Date()
}
updateTimestamp(): void {
this.updatedAt = new Date()
console.log(`用户 ${this.username} 时间戳已更新`)
}
activate(): void {
this.isActive = true
this.updateTimestamp()
console.log(`用户 ${this.username} 已激活`)
}
deactivate(): void {
this.isActive = false
this.updateTimestamp()
console.log(`用户 ${this.username} 已停用`)
}
getUserInfo(): string {
return `用户ID:${this.id},用户名:${this.username},状态:${this.isActive ? '活跃' : '停用'}`
}
}
实际应用案例:HarmonyOS UI组件类
下面展示如何在HarmonyOS应用中使用ArkTS类来管理UI状态。
// 定义数据模型类
class TodoItem {
constructor(
public id: string,
public title: string,
public completed: boolean = false,
public createdAt: Date = new Date()
) {}
toggleComplete(): void {
this.completed = !this.completed
}
updateTitle(newTitle: string): void {
this.title = newTitle
}
}
// 定义状态管理类
@Observed
class TodoList {
private items: TodoItem[] = []
addItem(title: string): void {
const newItem = new TodoItem(
Date.now().toString(),
title
)
this.items.push(newItem)
}
removeItem(id: string): void {
this.items = this.items.filter(item => item.id !== id)
}
toggleItem(id: string): void {
const item = this.items.find(item => item.id === id)
if (item) {
item.toggleComplete()
}
}
get completedCount(): number {
return this.items.filter(item => item.completed).length
}
get totalCount(): number {
return this.items.length
}
getItems(): TodoItem[] {
return [...this.items] // 返回副本
}
}
@Entry
@Component
struct TodoApp {
@State todoList: TodoList = new TodoList()
@State newItemTitle: string = ''
build() {
Column({ space: 20 }) {
Text('待办事项')
.fontSize(30)
.fontWeight(FontWeight.Bold)
Text(`总计:${this.todoList.totalCount},已完成:${this.todoList.completedCount}`)
.fontSize(16)
TextInput({ placeholder: '输入新事项' })
.width('90%')
.onChange((value: string) => {
this.newItemTitle = value
})
Button('添加事项')
.width('50%')
.onClick(() => {
if (this.newItemTitle.trim()) {
this.todoList.addItem(this.newItemTitle)
this.newItemTitle = ''
}
})
List({ space: 10 }) {
ForEach(this.todoList.getItems(), (item: TodoItem) => {
ListItem() {
Row({ space: 10 }) {
Text(item.title)
.fontSize(18)
.decoration({ type: item.completed ? TextDecorationType.LineThrough : TextDecorationType.None })
Checkbox()
.select(item.completed)
.onChange((checked: boolean) => {
this.todoList.toggleItem(item.id)
})
Button('删除')
.onClick(() => {
this.todoList.removeItem(item.id)
})
}
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
}
}, (item: TodoItem) => item.id)
}
.layoutWeight(1)
.width('100%')
}
.width('100%')
.height('100%')
.padding(20)
}
}
重要注意事项
版本兼容性
API级别说明:
- 本文代码基于HarmonyOS API 9编写
- 确保您的DevEco Studio和SDK版本兼容
- 部分高级特性可能需要更高API级别
常见陷阱与解决方案
1. 构造器中的属性初始化
// 错误示例
class ProblemClass {
name: string
// 忘记在构造器中初始化name
constructor() {
// 没有初始化name
}
}
// 正确做法
class CorrectClass {
name: string = '' // 提供默认值
constructor(name?: string) {
if (name) {
this.name = name
}
}
}
2. 接口实现完整性
interface RequiredMethods {
method1(): void
method2(): string
}
// 错误:没有实现所有接口方法
// class IncompleteClass implements RequiredMethods {
// method1(): void { }
// // 缺少method2
// }
// 正确:实现所有接口方法
class CompleteClass implements RequiredMethods {
method1(): void { }
method2(): string { return '' }
}
3. 访问控制注意事项
class AccessExample {
private secret: string = '机密信息'
// 正确:通过公共方法访问私有属性
getSecret(): string {
return this.secret
}
}
let example = new AccessExample()
// console.log(example.secret) // 错误:secret是私有的
console.log(example.getSecret()) // 正确:通过公共方法访问
性能优化建议
1. 避免过度使用继承
- 优先使用组合而非继承
- 保持继承层次简单(建议不超过3层)
2. 合理使用访问控制
- 将属性设置为private,通过方法控制访问
- 使用protected允许子类扩展,同时限制外部访问
3. 静态成员的使用场景
- 工具类方法适合作为静态方法
- 常量值适合作为静态属性
- 避免在静态方法中保存状态
总结
通过本文的学习,您应该已经掌握了ArkTS中类和接口的核心概念:
- 类定义:使用class关键字,包含属性、构造器和方法
- 接口:定义对象结构,确保实现一致性
- 继承:使用extends实现代码复用
- 访问控制:public、private、protected控制可见性
- 静态成员:属于类本身的属性和方法
- 抽象类:提供基础框架,要求子类实现特定方法
这些面向对象编程的概念是构建复杂HarmonyOS应用的基础。在实际开发中,合理运用这些特性可以提高代码的可维护性、可扩展性和重用性。
下一步学习建议:
- 深入学习ArkTS的泛型编程
- 掌握装饰器在HarmonyOS中的应用
- 学习状态管理和数据绑定的高级用法
- 实践更多HarmonyOS UI组件与ArkTS类的结合使用
继续探索ArkTS的强大功能,构建出色的HarmonyOS应用!
需要参加鸿蒙认证的请点击 鸿蒙认证链接

浙公网安备 33010602011771号