Day 09 - Class 基础
目标:掌握ArkTS类的定义、访问修饰符、Getter/Setter、静态成员
预计时间:1.5-2小时
前置知识:Day 01-05 基础语法、Day 06-08 函数
第一部分:类的定义(对标 C++ class/struct)
1.1 为什么需要类
问题引入:假设你要管理一组传感器数据,每个传感器有ID、名称、当前读数。不用类的话怎么写?
// 不用类:数据分散,容易出错
let sensorId: number = 1001;
let sensorName: string = "温度传感器-A1";
let sensorValue: number = 25.5;
let sensor2Id: number = 1002;
let sensor2Name: string = "湿度传感器-B2";
let sensor2Value: number = 60.0;
// 操作数据的函数也要分别处理
function updateSensorValue(value: number): void {
sensorValue = value; // 只能操作全局变量
}
问题:
- 变量名容易冲突(
sensorIdvssensor2Id) - 数据和操作分离,维护困难
- 无法创建多个结构相同的对象
解决方案:将数据和行为封装在一起 → 类
1.2 基本类定义
class Sensor {
// 属性声明:必须显式声明类型和初始值
id: number;
name: string;
currentValue: number;
// 构造函数
constructor(id: number, name: string, initialValue: number) {
this.id = id;
this.name = name;
this.currentValue = initialValue;
}
// 成员方法
updateValue(newValue: number): void {
this.currentValue = newValue;
}
getStatus(): string {
return `${this.name}: ${this.currentValue}`;
}
}
// 创建实例
let tempSensor: Sensor = new Sensor(1001, "温度传感器", 25.5);
let humiSensor: Sensor = new Sensor(1002, "湿度传感器", 60.0);
// 调用方法
tempSensor.updateValue(26.0);
console.log(`结果:${tempSensor.getStatus()}`); // "温度传感器: 26"
对比C++:
class Sensor {
public:
int id;
std::string name;
double currentValue;
Sensor(int id, const std::string& name, double initialValue)
: id(id), name(name), currentValue(initialValue) {}
void updateValue(double newValue) {
currentValue = newValue;
}
std::string getStatus() const {
return name + ": " + std::to_string(currentValue);
}
};
// 创建实例
Sensor tempSensor(1001, "温度传感器", 25.5);
tempSensor.updateValue(26.0);
关键差异:
- C++ 用
ClassName(params)构造,ArkTS 用new ClassName(params) - C++ 用初始化列表
: id(id), name(name),ArkTS 在构造函数内用this.id = id
1.3 属性必须有初始值
ArkTS严格要求:类属性必须有初始值,或在构造函数中赋值。
class Device {
// ✅ 方式1:声明时初始化
id: number = 0;
name: string = "";
// ✅ 方式2:在构造函数中赋值
serialNumber: string;
constructor(serial: string) {
this.serialNumber = serial; // 必须在这里赋值
}
}
// ❌ 错误:属性没有初始值,也没有在构造函数中赋值
class BadDevice {
id: number; // 错误!没有初始值
name: string; // 错误!没有初始值
// constructor 缺失或没有给属性赋值
}
对比C++:
- C++ 成员可以在构造函数初始化列表中赋值
- C++ 基本类型不初始化会有垃圾值,但不会编译错误
- ArkTS 强制要求明确初始化,更安全
第二部分:访问修饰符(对标 C++ public/private/protected)
2.1 public —— 默认就是public
重要区别:ArkTS 类成员默认就是 public,这与 C++ 默认 private 正好相反!
class Device {
// 这三行等价,都声明为 public
id: number;
public name: string;
public status: string;
constructor(id: number, name: string) {
this.id = id;
this.name = name;
this.status = "offline";
}
// 方法默认也是 public
turnOn(): void {
this.status = "online";
}
}
let dev: Device = new Device(1001, "灯-001");
console.log(`结果:${dev.id}`); // ✅ 可以访问
console.log(`结果:${dev.name}`); // ✅ 可以访问
dev.turnOn(); // ✅ 可以调用
对比C++:
class Device {
// C++ 默认是 private!
int id; // private
std::string name; // private
public:
// 必须显式声明 public 才能外部访问
void turnOn() { /* ... */ }
};
Device dev(1001, "灯-001");
// dev.id; // ❌ 编译错误,id 是 private
记忆口诀:ArkTS 默认"开放",C++ 默认"封闭"。
2.2 private —— 私有成员
class SecureDevice {
public id: number;
public name: string;
// private 成员:只能在类内部访问
private _password: string;
private _isLocked: boolean = true;
constructor(id: number, name: string, password: string) {
this.id = id;
this.name = name;
this._password = password;
}
// public 方法可以访问 private 成员
public unlock(password: string): boolean {
if (password === this._password) {
this._isLocked = false;
return true;
}
return false;
}
public operate(): string {
if (this._isLocked) {
return "设备已锁定,无法操作";
}
return "执行操作...";
}
// private 方法:内部辅助逻辑
private _logAccess(): void {
console.log(`结果:${this.name} 被访问`);
}
}
let device: SecureDevice = new SecureDevice(1001, "安全设备", "123456");
console.log(`结果:${device.id}`); // ✅ OK
// console.log(device._password); // ❌ 错误!private
// console.log(device._isLocked); // ❌ 错误!private
// device._logAccess(); // ❌ 错误!private
device.unlock("123456");
console.log(`结果:${device.operate()}`); // "执行操作..."
命名惯例:private 成员通常用 _ 前缀(如 _password),便于区分。
对比C++:用法完全相同,只是 ArkTS 需要显式写 private。
2.3 protected —— 子类可访问
class BaseDevice {
public id: number;
private _secret: string = "secret";
// protected:类内部和子类可以访问,外部不能
protected firmwareVersion: string = "1.0.0";
protected _updateFirmware(version: string): void {
this.firmwareVersion = version;
}
}
// 子类(Day 10 会详细讲继承)
class SmartLight extends BaseDevice {
updateToV2(): void {
// ✅ 子类可以访问 protected 成员
this._updateFirmware("2.0.0");
console.log(`结果:固件更新到 ${this.firmwareVersion}`);
}
}
let light: SmartLight = new SmartLight();
light.updateToV2(); // ✅ OK
// light._updateFirmware("3.0"); // ❌ 错误!外部不能访问 protected
// light.firmwareVersion; // ❌ 错误!外部不能访问 protected
预告:extends 继承语法将在 Day 10 详细讲解,这里只需理解 protected 的访问范围。
第三部分:属性进阶
3.1 readonly 属性 —— 只读属性
问题引入:设备的ID一旦创建就不应该改变,怎么限制?
class DeviceConfig {
readonly id: number; // 只读属性
readonly createdAt: number; // 只读属性
name: string;
constructor(id: number, name: string) {
this.id = id; // ✅ 构造函数中可以赋值
this.createdAt = Date.now(); // ✅ 构造函数中可以赋值
this.name = name;
}
updateName(newName: string): void {
this.name = newName; // ✅ OK
// this.id = 999; // ❌ 错误!readonly 属性不能修改
}
}
let config: DeviceConfig = new DeviceConfig(1001, "配置-001");
console.log(`结果:ID=${config.id}, 创建时间=${config.createdAt}`);
// config.id = 1002; // ❌ 编译错误
对比C++:
class DeviceConfig {
public:
const int id; // const 成员 = readonly
const long long createdAt;
std::string name;
DeviceConfig(int id, const std::string& name)
: id(id), createdAt(std::time(nullptr)), name(name) {}
};
共同点:都只能在构造函数中初始化,之后不能修改。
第四部分:Getter / Setter(对标 C++ 手写getter/setter,但语法更优雅)
4.1 基本语法
C++ 风格:手动写 get/set 方法。
class CppStyleDevice {
private _brightness: number = 0;
getBrightness(): number {
return this._brightness;
}
setBrightness(value: number): void {
this._brightness = value;
}
}
let dev: CppStyleDevice = new CppStyleDevice();
dev.setBrightness(80);
console.log(`结果:${dev.getBrightness()}`);
ArkTS 风格:使用 get / set 关键字,像访问属性一样调用。
class DimmableLight {
private _brightness: number = 0;
// getter:像属性一样读取
get brightness(): number {
return this._brightness;
}
// setter:像属性一样赋值
set brightness(value: number) {
this._brightness = value;
}
}
let light: DimmableLight = new DimmableLight();
light.brightness = 80; // 调用 setter
console.log(`结果:${light.brightness}`); // 调用 getter,输出 80
优势:使用方代码更简洁,像直接访问属性,但内部可以添加逻辑。
4.2 数据验证 —— 在setter中添加验证
class ValidatedLight {
private _brightness: number = 0;
private _isOn: boolean = false;
get brightness(): number {
return this._brightness;
}
// setter 中加入验证逻辑
set brightness(value: number) {
if (value < 0 || value > 100) {
console.log("错误:亮度必须在0-100之间");
return;
}
this._brightness = value;
this._isOn = value > 0;
}
get isOn(): boolean {
return this._isOn;
}
}
let light: ValidatedLight = new ValidatedLight();
light.brightness = 80; // ✅ 正常设置
console.log(`结果:亮度=${light.brightness}, 状态=${light.isOn}`);
light.brightness = 150; // ❌ 输出错误信息,不会设置
console.log(`结果:亮度=${light.brightness}`); // 仍然是 80
4.3 计算属性 —— 在getter中返回计算值
class PowerDevice {
private _brightness: number = 0;
private readonly _maxPower: number = 50; // 最大功率50W
get brightness(): number {
return this._brightness;
}
set brightness(value: number) {
this._brightness = Math.max(0, Math.min(100, value));
}
// 计算属性:根据亮度计算功耗
get powerConsumption(): number {
return (this._brightness / 100) * this._maxPower;
}
// 计算属性:根据亮度估算寿命剩余百分比
get estimatedLifeRemaining(): number {
// 假设满亮度寿命10000小时,每降低10%亮度寿命增加20%
let factor: number = 1 + (100 - this._brightness) / 10 * 0.2;
return 100 / factor;
}
}
let device: PowerDevice = new PowerDevice();
device.brightness = 80;
console.log(`结果:功耗=${device.powerConsumption}W`); // 40W
console.log(`结果:寿命剩余=${device.estimatedLifeRemaining}%`); // 计算值
4.4 私有属性 + 公开访问器模式
这是封装的最佳实践:
class TemperatureSensor {
private _celsius: number = 0;
// 摄氏度读写
get celsius(): number {
return this._celsius;
}
set celsius(value: number) {
if (value < -273.15) {
console.log("错误:温度不能低于绝对零度");
return;
}
this._celsius = value;
}
// 华氏度只读(计算属性)
get fahrenheit(): number {
return this._celsius * 9 / 5 + 32;
}
// 开尔文只读(计算属性)
get kelvin(): number {
return this._celsius + 273.15;
}
}
let sensor: TemperatureSensor = new TemperatureSensor();
sensor.celsius = 25;
console.log(`结果:${sensor.celsius}°C = ${sensor.fahrenheit}°F = ${sensor.kelvin}K`);
// sensor.fahrenheit = 100; // ❌ 错误!没有 setter
4.5 Getter/Setter 的局限性与最佳实践
局限性 1:属性与访问器不能同名
ArkTS 限制:类的属性(无论访问修饰符)和 getter/setter 不能使用相同的标识符名。
// ❌ 错误:Duplicate identifier 'port'
class Device {
private port: number = 25; // 属性叫 port
get port(): number {
...
} // ❌ 重名!编译错误
set port(value: number) {
...
} // ❌ 重名!
}
// ✅ 正确:属性使用下划线前缀
class Device {
private _port: number = 25; // 属性加下划线
get port(): number { // getter 无下划线
return this._port;
}
set port(value: number) { // setter 无下划线
this._port = value;
}
}
局限性 2:Setter 禁止返回类型注解
class Light {
private _brightness: number = 0;
// ❌ 错误:ArkTS 不允许写 :void
set brightness(value: number): void {
this._brightness = value;
}
// ✅ 正确:必须省略返回类型
set brightness(value: number) {
this._brightness = value;
}
}
局限性 3:Setter 无法返回值
Setter 不能返回任何值,调用方无法直接知道设置是否成功:
class ValidatedLight {
private _brightness: number = 0;
set brightness(value: number) {
if (value < 0 || value > 100) {
console.log("错误:亮度超出范围");
return; // 只能直接返回,不能返回 false
}
this._brightness = value;
}
}
let light = new ValidatedLight();
light.brightness = 150; // 设置失败,但调用方无法知道
解决方案:如果需要知道操作结果,使用普通方法代替 setter:
class BetterLight {
private _brightness: number = 0;
// 用方法代替 setter,可以返回 boolean
setBrightness(value: number): boolean {
if (value < 0 || value > 100) {
return false; // 返回失败
}
this._brightness = value;
return true; // 返回成功
}
get brightness(): number {
return this._brightness;
}
}
let light = new BetterLight();
let ok = light.setBrightness(150);
if (!ok) {
console.log("设置失败");
}
最佳实践建议
| 场景 | 推荐方案 |
|---|---|
| 简单属性读写,无需验证 | 直接暴露 public 属性 |
| 需要验证/计算,但不需要返回结果 | 使用 getter/setter |
| 需要知道操作是否成功 | 使用普通方法,返回 boolean |
| 只读计算属性 | 只提供 getter,不提供 setter |
第五部分:Static 成员(对标 C++ static)
5.1 静态属性 —— 类级别共享数据
问题引入:如何统计创建了多少个设备实例?
class DeviceManager {
// 静态属性:所有实例共享同一个变量
static instanceCount: number = 0;
static readonly MAX_DEVICES: number = 100;
// 实例属性:每个实例独立
id: number;
name: string;
constructor(name: string) {
if (DeviceManager.instanceCount >= DeviceManager.MAX_DEVICES) {
throw new Error("设备数量已达上限");
}
this.id = ++DeviceManager.instanceCount;
this.name = name;
}
}
let d1: DeviceManager = new DeviceManager("设备-A");
let d2: DeviceManager = new DeviceManager("设备-B");
let d3: DeviceManager = new DeviceManager("设备-C");
console.log(`结果:实例1 ID=${d1.id}`); // 1
console.log(`结果:实例2 ID=${d2.id}`); // 2
console.log(`结果:实例3 ID=${d3.id}`); // 3
console.log(`结果:总实例数=${DeviceManager.instanceCount}`); // 3
console.log(`结果:上限=${DeviceManager.MAX_DEVICES}`); // 100
对比C++:
class DeviceManager {
public:
static int instanceCount;
static const int MAX_DEVICES = 100;
DeviceManager(const std::string& name) {
id = ++instanceCount;
this->name = name;
}
int id;
std::string name;
};
// C++ 必须在类外初始化静态成员
int DeviceManager::instanceCount = 0;
重要注意:静态属性如果不初始化,值为 undefined,不是默认值!
class Test {
static num: number; // 未初始化,值是 undefined,不是 0!
static str: string; // 未初始化,值是 undefined,不是 ""!
static flag: boolean; // 未初始化,值是 undefined,不是 false!
}
console.log(Test.num); // undefined
console.log(Test.str); // undefined
console.log(Test.flag); // undefined
建议:静态属性始终显式初始化,避免意外。
5.2 静态方法 —— 通过类名调用
class MathUtils {
// 静态方法:不依赖实例状态
static clamp(value: number, min: number, max: number): number {
return Math.max(min, Math.min(max, value));
}
static degToRad(degrees: number): number {
return degrees * Math.PI / 180;
}
static radToDeg(radians: number): number {
return radians * 180 / Math.PI;
}
}
// 直接通过类名调用,不需要创建实例
let clamped: number = MathUtils.clamp(150, 0, 100);
console.log(`结果:限制在0-100之间:${clamped}`); // 100
let rad: number = MathUtils.degToRad(180);
console.log(`结果:180度 = ${rad}弧度`); // 3.14159...
5.3 实用场景 —— 计数器、工厂方法
class DeviceFactory {
private static _serialCounter: number = 0;
// 工厂方法:创建带自动序列号的设备
static createDevice(name: string): DeviceInfo {
DeviceFactory._serialCounter++;
return new DeviceInfo(
DeviceFactory._serialCounter,
`${name}-${DeviceFactory._serialCounter}`
);
}
static getTotalCreated(): number {
return DeviceFactory._serialCounter;
}
}
class DeviceInfo {
constructor(
public id: number,
public name: string
) {
}
}
// 使用工厂方法创建设备
let dev1: DeviceInfo = DeviceFactory.createDevice("传感器");
let dev2: DeviceInfo = DeviceFactory.createDevice("传感器");
let dev3: DeviceInfo = DeviceFactory.createDevice("执行器");
console.log(`结果:${dev1.name}`); // "传感器-1"
console.log(`结果:${dev2.name}`); // "传感器-2"
console.log(`结果:${dev3.name}`); // "执行器-3"
console.log(`结果:总计创建=${DeviceFactory.getTotalCreated()}`); // 3
第六部分:小结与练习
6.1 知识点对比总结表(ArkTS vs C++)
| 概念 | C++ | ArkTS | 关键差异 |
|---|---|---|---|
| 类定义 | class |
class |
相同 |
| 构造函数 | ClassName(params) |
constructor(params) |
关键字不同 |
| 构造函数重载 | ✅ 支持 | ❌ 不支持 | ArkTS 只能用默认参数模拟 |
| 属性初始化 | 初始化列表 | 构造函数内 this.x = x |
语法不同 |
| 默认访问修饰符 | private |
public |
重要区别 |
| public | public: |
public(可省略) |
ArkTS默认就是public |
| private | private: |
private |
用法相同,但ArkTS一对一声明 |
| protected | protected: |
protected |
用法相同 |
| readonly/const | const成员 |
readonly |
关键字不同 |
| 参数属性简写 | 无 | ❌ ArkTS不支持 | TypeScript支持,ArkTS禁止 |
| getter/setter | 手动方法 | get/set关键字 |
ArkTS语法更优雅但有局限 |
| setter返回类型 | 任意 | ❌ 禁止写返回类型 | ArkTS特殊限制 |
| 属性与访问器重名 | ✅ 允许 | ❌ 禁止 | ArkTS限制:Duplicate identifier |
| 静态成员 | static |
static |
ArkTS可在类内初始化 |
| 静态属性默认值 | 自动初始化 | undefined |
ArkTS不初始化则为undefined |
6.2 练习题
练习1:选择题
-
ArkTS类成员默认的访问修饰符是?
- A. private
- B. public
- C. protected
- D. 没有默认值
-
以下哪个是ArkTS合法的readonly属性用法?
- A.
readonly x: number = 0;声明时初始化 - B. 在构造函数中赋值
- C. 以上都是
- D. 以上都不是
- A.
-
ArkTS枚举的限制是?
- A. 不能用于switch语句
- B. 不能同时包含数字和字符串成员
- C. 必须显式指定所有值
- D. 最多只能有10个成员
练习1答案
答案:1.B 2.C 3.B
| 题号 | 答案 | 解析 |
|---|---|---|
| 1 | B | ArkTS 类成员默认就是 public,与 C++ 默认 private 相反 |
| 2 | C | readonly 属性可以在声明时初始化,也可以在构造函数中赋值,之后不能修改 |
| 3 | B | ArkTS 枚举禁止混合类型(不能同时有数字和字符串成员) |
练习2:代码补全
补全以下类定义,实现一个带验证的邮箱配置类:
class EmailConfig {
readonly id: number;
address: string; // public 属性
// 补全:smtpServer 是 private,字符串类型
______
______: ______;
// 补全:_port 是 private,number类型,默认25(注意:属性名用_port,避免与getter/setter重名)
______
______: ______ = ______;
constructor(
id: number,
address: string,
server: string
) {
this.id = id;
this.address = address;
this.smtpServer = server;
}
// 补全:port的getter(注意:getter名叫port,属性名叫_port)
get ______(): ______ {
return this._port;
}
// 补全:port的setter,验证范围1-65535
set ______(value: ______) {
if (value < 1 || value > 65535) {
console.log("端口范围错误");
return;
}
this._port = value;
}
}
练习2答案
class EmailConfig {
readonly id: number;
address: string;
private smtpServer: string;
private _port: number = 25;
constructor(
id: number,
address: string,
server: string
) {
this.id = id;
this.address = address;
this.smtpServer = server;
}
get port(): number {
return this._port;
}
set port(value: number) {
if (value < 1 || value > 65535) {
console.log("端口范围错误");
return;
}
this._port = value;
}
}
练习3:编程题 - 实现一个计数器类
要求:
- 类名
Counter - 静态属性
totalCounters记录创建的实例总数 - 实例属性
id(readonly)、name、count - 方法
increment()增加count - 方法
decrement()减少count(不能小于0) - 方法
reset()重置count为0 - getter
value返回当前count
练习3答案
class Counter {
static totalCounters: number = 0;
readonly id: number;
name: string;
count: number = 0;
constructor(id: number, name: string, count: number = 0) {
Counter.totalCounters++;
this.id = id;
this.name = name;
this.count = count;
}
increment(): void {
this.count++;
}
decrement(): void {
if (this.count > 0) {
this.count--;
}
}
reset(): void {
this.count = 0;
}
get value(): number {
return this.count;
}
}
练习5:编程题 - 温度转换类
实现 Temperature 类:
- private属性
_celsius: number - getter/setter
celsius - getter
fahrenheit(只读,计算属性) - getter
kelvin(只读,计算属性) - setter验证:celsius不能低于-273.15
练习5答案
class Temperature {
private _celsius: number = 0;
constructor(c: number) {
if (c < -273.15) {
console.log("温度不能低于绝对零度,初始化为0");
this._celsius = 0;
return;
}
this._celsius = c;
}
get celsius(): number {
return this._celsius;
}
set celsius(c: number) {
if (c < -273.15) {
console.log("温度不能低于绝对零度");
return;
}
this._celsius = c;
}
get fahrenheit(): number {
return this._celsius * 9 / 5 + 32;
}
get kelvin(): number {
return this._celsius + 273.15;
}
}
练习6:编程题 - 单例模式(静态方法应用)
实现 ConfigManager 类:
- private static属性
_instance: ConfigManager | null = null - public static方法
getInstance(): ConfigManager,返回唯一实例 - 实例属性
settings: Map<string, string> - 实例方法
set(key: string, value: string): void - 实例方法
get(key: string): string | undefined
练习6答案
class ConfigManager {
private static _instance: ConfigManager | null = null;
private settings: Map<string, string>;
private constructor() {
this.settings = new Map<string, string>();
}
static getInstance(): ConfigManager {
if (ConfigManager._instance === null) {
ConfigManager._instance = new ConfigManager();
}
return ConfigManager._instance;
}
set(key: string, value: string): void {
this.settings.set(key, value);
}
get(key: string): string | undefined {
return this.settings.get(key);
}
}
练习7:编程题 - 带权限检查的设备类
实现 SecureDevice 类:
- readonly属性
deviceId: number - private属性
_accessCode: string、_isAuthorized: boolean = false - 构造函数接收 deviceId 和 accessCode
- 方法
authorize(code: string): boolean,验证code是否正确 - 方法
operate(): string,只有授权后才能操作 - protected属性
_firmwareVersion: string = "1.0.0" - protected方法
_updateFirmware(version: string): void
练习7答案
class SecureDevice {
readonly deviceId: number;
protected _firmwareVersion: string = "1.0.0";
private _accessCode: string;
private _isAuthorized: boolean = false;
constructor(deviceId: number, accessCode: string) {
this.deviceId = deviceId;
this._accessCode = accessCode;
}
authorize(code: string): boolean {
this._isAuthorized = (code === this._accessCode);
return this._isAuthorized;
}
operate(): string {
if (!this._isAuthorized) {
return "鉴权失败,禁止操作";
}
return `设备 ${this.deviceId} 操作成功`;
}
protected _updateFirmware(version: string): void {
if (version !== this._firmwareVersion) {
this._firmwareVersion = version;
}
}
}
练习8:综合题 - 设备管理器
结合所学知识,实现一个简单的设备管理系统:
// 1. 定义设备类型枚举(字符串枚举)
enum DeviceType {
SENSOR = "sensor",
ACTUATOR = "actuator",
CONTROLLER = "controller"
}
// 2. 实现 Device 基类
// - readonly id, name
// - protected type: DeviceType
// - private _isActive: boolean = false
// - getter/setter active(setter中记录日志)
// - 抽象方法 activate()/deactivate()(用空方法模拟)
// 3. 实现 DeviceManager 类
// - static属性 devices: Device[] = []
// - static方法 register(device: Device): void
// - static方法 findById(id: number): Device | undefined
// - static方法 getActiveCount(): number
// - static方法 listAll(): string[]
练习8答案
enum DeviceType {
SENSOR = "sensor",
ACTUATOR = "actuator",
CONTROLLER = "controller"
}
class Device {
readonly id: number;
readonly name: string;
protected type: DeviceType;
private _isActive: boolean = false;
constructor(id: number, name: string, type: DeviceType) {
this.id = id;
this.name = name;
this.type = type;
}
get active(): boolean {
return this._isActive;
}
set active(value: boolean) {
console.log(`设备 ${this.id} 状态变为: ${value ? "激活" : "未激活"}`);
this._isActive = value;
}
activate(): void {
console.log(`设备 ${this.id} 正在激活...`);
this.active = true;
}
deactivate(): void {
console.log(`设备 ${this.id} 正在关闭...`);
this.active = false;
}
}
class DeviceManager {
static devices: Device[] = [];
static register(device: Device): void {
if (DeviceManager.findById(device.id) === undefined) {
DeviceManager.devices.push(device);
}
}
static findById(id: number): Device | undefined {
for (let i = 0; i < DeviceManager.devices.length; i++) {
if (DeviceManager.devices[i].id === id) {
return DeviceManager.devices[i];
}
}
return undefined;
}
static getActiveCount(): number {
let count = 0;
for (let i = 0; i < DeviceManager.devices.length; i++) {
if (DeviceManager.devices[i].active) {
count++;
}
}
return count;
}
static listAll(): string[] {
let list: string[] = [];
for (let i = 0; i < DeviceManager.devices.length; i++) {
let d = DeviceManager.devices[i];
list.push(`${d.id}: ${d.name} - ${d.active ? "激活" : "未激活"}`);
}
return list;
}
}
附录:ArkTS Class 速查表
// 基础类定义
class MyClass {
// 属性必须有初始值或在构造函数中赋值
publicProp: number = 0;
private _privateProp: string = "";
protected protectedProp: boolean = false;
readonly readOnlyProp: number;
constructor(initialValue: number) {
this.readOnlyProp = initialValue;
}
// 方法
publicMethod(): void {
}
private _privateMethod(): void {
}
protected protectedMethod(): void {
}
}
// 注意:ArkTS 不支持参数属性简写!
// 以下写法在 TypeScript 中合法,但在 ArkTS 中会报错:
// class ShortClass {
// constructor(
// public id: number, // ❌ ArkTS 错误:arkts-no-ctor-prop-decls
// private _secret: string,
// readonly createdAt: number
// ) {}
// }
// ✅ ArkTS 正确写法:先声明属性,再赋值
class ShortClass {
id: number;
private _secret: string;
readonly createdAt: number;
constructor(id: number, secret: string, createdAt: number) {
this.id = id;
this._secret = secret;
this.createdAt = createdAt;
}
}
// Getter / Setter
// 注意:ArkTS 中属性与 getter/setter 不能同名!
// 属性用 _前缀,getter/setter 用无前缀名
class WithAccessor {
private _value: number = 0; // 属性名:_value
get value(): number { // getter 名:value(不能叫 _value)
return this._value;
}
set value(v: number) { // setter 名:value(不能叫 _value)
this._value = v;
}
}
// 静态成员
class StaticDemo {
static count: number = 0;
static readonly MAX: number = 100;
static getCount(): number {
return StaticDemo.count;
}
}

浙公网安备 33010602011771号