引言
在开发智能家居控制应用时,若不使用类,需要为每个设备单独定义变量与功能函数,代码繁琐且无法将同一设备的属性与逻辑关联起来。类是面向对象编程的核心容器,用于将同一对象的属性(特征)和方法(操作)打包在一起,作为创建对象的模板,实现代码模块化。本节课将系统讲解 ArkTS 中类与接口的声明、使用及面向对象三大核心特征。
核心内容
为什么需要类
不使用类的零散写法:
let name = '灯'; let brightness = 59; let status = 'off'; let location = ''; function setBrightness(brightnessParam: number) { brightness = brightnessParam; } function setStatus(statusParam: string) { status = statusParam; } function setLocation(locationParam: string) { location = locationParam; }使用类封装后的写法:
class Light { name = '灯'; brightness = 59; status = 'off'; location = ''; setBrightness(brightnessParam: number) { this.brightness = brightnessParam; } setStatus(statusParam: string) { this.status = statusParam; } setLocation(locationParam: string) { this.location = locationParam; } }类的作用是将同一个设备的属性和功能打包在一个容器中,是面向对象编程的核心载体。
类的声明与使用
声明语法
使用class关键字声明类,类名首字母大写(遵循命名规范),类体用{}包裹。类中可定义属性(属性名: 类型 = 属性值)和方法(方法名 + 参数 + 方法体)。
class Device { name: string = ''; // 定义属性 // 定义方法 getInfo(): string { return `${this.name}`; } }构造函数与类的实例化
构造函数规则
使用constructor关键字声明构造函数,通过new创建实例时自动执行,核心作用是初始化实例属性。this指向当前正在创建的实例对象。
带参数的构造函数示例:
class Device { name: string = ''; type: string = 'light'; location: string = 'bedroom'; constructor(name: string, type: string, location: string) { this.name = name; this.type = type; this.location = location; } } // 传入参数实例化 let device: Device = new Device('客厅空调', '空调', '客厅');默认构造函数规则:
若未显式定义构造函数,ArkTS 会自动生成无参默认构造函数,使用字段类型的默认值初始化实例属性。一旦自定义了任意构造函数(无论是否带参),编译器将停止生成默认构造函数,无参调用会直接报错。
错误示例:
class Device { name: string = ''; constructor(name: string) { this.name = name; } } let device: Device = new Device(); // 报错:预期有1个参数,但实际未提供任何参数对象字面量创建实例
除new关键字外,可通过对象字面量{}包裹键值对快速初始化类实例。
class Device { name: string = ''; } // 方式一:new 关键字创建实例 let device1 = new Device(); // 方式二:对象字面量创建实例 let device2: Device = { name: '智能手表' };对象字面量与new关键字的区别:
| 特性 | 对象字面量 | new关键字 |
|---|---|---|
| 实例化方式 | 直接通过{}初始化属性,无需调用构造函数 | 会调用类的构造函数 |
| 构造函数执行 | 不执行类中的构造函数逻辑 | 自动执行构造函数中的初始化逻辑 |
| 类型检查严格性 | 属性必须严格匹配类定义(类型、名称一致) | 自动满足类定义,无需额外类型标注 |
| 适用场景 | 轻量级数据模型、无复杂初始化逻辑的简单类 | 需要构造函数逻辑、方法继承的复杂类 |
对象字面量必须包含类中声明的所有必选属性,不支持创建包含方法的类实例(方法必须通过构造函数初始化)。
类的属性分类
| 属性类型 | 关键字 | 归属 | 访问方式 | 特点 |
|---|---|---|---|---|
| 实例属性 | 无 | 每个实例独立拥有 | 实例名.属性名 | 需创建实例后访问 |
| 静态属性 | static | 属于类本身 | 类名.属性名 | 所有实例共享,实例无法访问 |
| 只读属性 | readonly | 实例或类 | 赋值后不可修改 | 常与static结合定义类级常量 |
示例代码:
class Device { name: string = '未知设备'; // 静态只读属性:所有设备共享的品牌信息 static readonly brand: string = '智能家居'; } // 访问实例属性 let device = new Device(); console.log(device.name); // 输出:未知设备 device.name = '灯'; // 实例属性可重新赋值 // 访问静态属性 console.log(Device.brand); // 输出:智能家居 Device.brand = '其他'; // 报错:无法修改只读属性 device.brand; // 报错:实例不存在 brand 属性类属性与普通变量的区别:
| 维度 | 普通变量(let/const声明) | 类属性 |
|---|---|---|
| 定义位置 | 可在任何作用域声明 | 类内部声明,通过修饰符修饰 |
| 调用方式 | 直接调用 | 通过对象或类名(静态属性)调用 |
| 生命周期 | 由作用域决定(如函数执行完毕即销毁) | 与类实例同生命周期 |
类的方法
方法定义和函数类似,但不需要function关键字,直接在类内部写方法名、参数、方法体即可。
| 方法类型 | 关键字 | 归属 | 调用方式 |
|---|---|---|---|
| 实例方法 | 无 | 属于实例 | 实例名.方法名() |
| 静态方法 | static | 属于类 | 类名.方法名() |
函数不依赖类/对象,可独立声明直接调用;方法是依附于类的函数,必须定义在类内部,通过实例或类名调用。
面向对象三大核心特征
继承
作用:抽取多个子类的公共属性和方法到父类,子类继承后直接复用公共逻辑,同时保留自身特有属性方法,减少重复代码。
语法:通过extends关键字实现,ArkTS 中类只支持单继承,即一个子类只能有一个父类。
重要规则:如果子类定义了自己的构造函数,必须在构造函数中通过super()调用父类的构造函数,否则编译器会报错。
封装
作用:将数据和方法封装在类内部,通过访问修饰符隐藏内部实现,只对外暴露必要的访问接口,保证数据的一致性和安全性。
| 修饰符 | 访问范围 | 说明 |
|---|---|---|
public(默认) | 类内部、子类、外部均可访问 | 未加修饰符的属性和方法默认都是public |
private | 仅允许在当前类内部访问 | 子类和外部均不可访问,用于封装敏感数据或内部逻辑 |
protected | 允许在当前类内部和子类中访问 | 外部不可访问 |
多态
原理:基于继承实现,子类继承父类后可以重写父类的方法,不同子类对同一方法的实现逻辑不同。使用父类类型引用不同子类实例调用方法时,会呈现不同的执行结果。
方法重写规则:
子类方法必须与父类方法同名。
参数的类型、顺序、数量完全一致。
返回值类型与父类相同或为其子类。
访问权限不能比父类更严格。
抽象类
定义:通过abstract关键字修饰,作为子类的规范模板,定义子类必须实现的抽象方法。
规则:
抽象类不能直接实例化。
抽象类中既可以定义只有方法签名没有方法体的抽象方法,也可以定义已经实现的普通方法。
子类继承抽象类后,必须实现所有抽象方法,否则编译器报错。
接口的声明与使用
作用:接口用于约束类的结构,规定类必须包含哪些属性和方法,只定义结构规范,不提供具体实现。
语法:通过interface关键字声明。接口中的方法只有方法签名没有方法体,属性只有类型没有初始值。
核心特性:
接口支持多继承,一个接口可以同时继承多个父接口。
类通过
implements关键字实现接口,一个类可以同时实现多个接口。实现接口时,必须实现接口要求的所有属性和方法,否则编译器报错。
抽象类与接口的核心区别
| 对比维度 | 接口 | 抽象类 |
|---|---|---|
| 核心定位 | 专注于结构规范,只声明属性和方法,不提供实现 | 侧重模板和逻辑复用,既可以定义抽象方法,也可以提供完整实现 |
| 继承/实现规则 | 支持多继承、多实现,一个类可实现多个接口 | 仅支持单继承,一个子类只能继承一个抽象类 |
| 成员特性 | 所有成员默认公开,不支持静态属性和方法 | 支持用访问修饰符控制权限,支持静态成员 |
| 实例化 | 不能直接实例化 | 不能直接实例化 |
总结
本节课系统讲解了 ArkTS 中类与接口的核心知识:
类的声明与实例化:通过
class关键字声明,支持new关键字和对象字面量两种实例化方式。构造函数通过constructor声明,自定义构造后默认无参构造失效。类的属性与方法:属性分为实例属性、静态属性(
static)和只读属性(readonly);方法分为实例方法和静态方法,均无需function关键字。面向对象三大特征:
封装:通过
public/private/protected三种修饰符实现。继承:通过
extends实现单继承,子类自定义构造必须调用super()。多态:子类重写父类方法实现差异化行为,需遵循方法重写签名规则。
抽象类与接口:两者均不能直接实例化。抽象类(
abstract)侧重模板和逻辑复用,支持单继承;接口(interface)侧重结构规范,支持多继承和多实现。