在这里插入图片描述

1、类和对象

在面向对象编程(OOP)中,类(Class) 是创建对象的蓝图或模板,它封装了数据(字段)和行为(方法)。ArkTS 作为强类型语言,全面支持类的定义与使用,并在 TypeScript 的基础上强化了类型安全和编译期检查。

在以下示例中,我们定义了一个 Person 类,包含两个字段 namesurname、一个构造函数以及一个用于拼接全名的方法 fullName

在这里插入图片描述

通过 new Person(...) 可以创建该类的实例(即对象),每个实例都拥有独立的数据状态和共享的行为逻辑。


1.1、字段

字段(Field) 是类中声明的变量,用于存储对象的状态。ArkTS 支持两种类型的字段:实例字段静态字段

1.1.1、实例字段

实例字段属于类的每一个具体对象(实例),每个实例都拥有自己的一份副本。要访问实例字段,必须通过类的实例进行。

class Person {
  name: string = '';
  age: number = 0;

  constructor(n: string, a: number) {
    this.name = n;
    this.age = a;
  }

  getName(): string {
    return this.name;
  }
}

let p1 = new Person('Alice', 25);
console.log(p1.name); // 输出:Alice

let p2 = new Person('Bob', 28);
console.log(p2.getName()); // 输出:Bob

💡 说明:实例字段通常用于表示对象的“个体属性”,如人的姓名、年龄、ID 等。它们在内存中为每个对象单独分配空间。

在这里插入图片描述

1.1.2、静态字段

使用 static 关键字声明的字段称为静态字段。静态字段不属于任何实例,而是属于类本身,所有实例共享同一个静态字段。

访问静态字段时,应通过类名而非实例:

class Counter {
  static count: number = 0;

  constructor() {
    Counter.count++;
  }
}

new Counter(); // count = 1
new Counter(); // count = 2
console.log(Counter.count); // 输出:2

典型用途:计数器、全局配置、工具类常量等不需要依赖具体实例的场景。

在这里插入图片描述


1.2、方法

方法(Method) 是定义在类中的函数,用于描述对象的行为。ArkTS 支持实例方法静态方法

1.2.1、实例方法

实例方法作用于类的某个具体实例,可以访问该实例的所有字段(包括私有字段)以及静态成员。

以下示例中,calculateArea 是一个实例方法,用于计算矩形面积:

class RectangleSize {
  private height: number = 0;
  private width: number = 0;

  constructor(height: number, width: number) {
    this.height = height;
    this.width = width;
  }

  calculateArea(): number {
    return this.height * this.width; // 可访问私有字段
  }
}

🔒 封装性体现:通过将 heightwidth 声明为 private,外部无法直接修改,只能通过方法间接操作,增强了数据安全性。

在这里插入图片描述

1.2.2、静态方法

使用 static 关键字声明的方法为静态方法。它属于类本身,不能访问实例字段(因为没有 this 上下文),但可以访问静态字段。

静态方法通常用于提供与类相关但不依赖具体实例的工具功能:

class MathUtils {
  static add(a: number, b: number): number {
    return a + b;
  }

  static PI: number = 3.14159;
  static circleArea(r: number): number {
    return this.PI * r * r; // 可访问静态字段
  }
}

console.info(MathUtils.add(2, 3));        // 5
console.info(MathUtils.circleArea(2));   // ≈12.566

调用时必须使用类名:

console.info(Cl.staticMethod());

⚠️ 注意:静态方法中不能使用 this 指向实例,也不能调用非静态方法。

在这里插入图片描述


1.3、构造函数

构造函数(Constructor) 是在创建类实例时自动调用的特殊方法,用于初始化对象的字段。

ArkTS 要求如果类包含未初始化的字段,必须提供构造函数进行赋值(除非字段有默认值)。

在 DevEco Studio 中,可通过右键 → Generate 快速生成构造函数:

在这里插入图片描述

选择需要初始化的字段:

在这里插入图片描述

确认后自动生成构造函数代码:

在这里插入图片描述

最终类结构完整生成:

在这里插入图片描述

🛠️ 开发效率提示:利用 IDE 的代码生成功能,可大幅减少样板代码编写,避免手误。


1.4、构造方法(实例化与使用)

定义好类后,可在其他文件(如页面组件)中导入并使用。

首先,在类所在文件中确保类被导出:

export class Person { ... }

在这里插入图片描述

然后在 Index.ets 页面中通过 import 引入:

import { Person } from './Person';

即可创建实例并调用其方法:

let p = new Person('VON', 20);
console.log(p.getName());

在这里插入图片描述

📦 模块化思想:将类定义在独立文件中并导出,是构建大型应用的基础,有助于代码解耦与复用。


1.5、对象字面量

对象字面量是一种简洁的语法,用于直接创建符合某类结构的对象,而无需显式调用 new

其形式为:{ 属性名: 值, ... }

class C {
  n: number = 0;
  s: string = '';
}

let c: C = { n: 42, s: 'foo' };

⚠️ 重要限制:ArkTS 是静态类型语言,对象字面量只能在类型可被明确推断的上下文中使用,例如:

  • 赋值给已声明类型的变量;
  • 作为函数参数(参数有类型);
  • 作为函数返回值(返回类型已知);
  • 作为数组元素(数组元素类型已知)。

合法示例:

function foo(c: C) {}
let c: C;
c = { n: 42, s: 'foo' };           // ✅ 变量类型已知
foo({ n: 42, s: 'foo' });          // ✅ 参数类型已知
function bar(): C {
  return { n: 42, s: 'foo' };      // ✅ 返回类型已知
}
let cc: C[] = [{ n: 1, s: 'a' }, { n: 2, s: 'b' }]; // ✅ 数组元素类型已知

❌ 若写成 let obj = { n: 1, s: 'a' }; 而未指定类型,则 obj 会被推断为匿名对象类型,不能赋值给 C 类型变量

在这里插入图片描述


1.6、抽象类

使用 abstract 修饰符声明的类称为抽象类。它不能被直接实例化,通常用于定义一组子类的公共接口或行为骨架。

abstract class Animal {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
  abstract makeSound(): void; // 抽象方法
}

// new Animal('test'); // ❌ 编译错误:不能实例化抽象类

抽象类的子类可以是:

  • 非抽象类:必须实现所有抽象方法,可被实例化;
  • 抽象类:可继续定义新的抽象方法。

🧱 设计意义:抽象类体现了“共性提取”思想,适用于具有共同特征但行为各异的类族(如动物、图形、用户角色等)。

在这里插入图片描述


1.7、抽象方法

抽象方法是只有声明、没有实现的方法,使用 abstract 关键字定义。

关键规则:

  • 抽象方法只能出现在抽象类中
  • 非抽象类若包含抽象方法,将导致编译错误

错误示例:

class Y {
  abstract method(p: string); // ❌ 编译错误:抽象方法只能在抽象类内。
}

正确做法:

abstract class Base {
  abstract method(p: string): void;
}

class Derived extends Base {
  method(p: string): void {
    console.log('Implemented:', p);
  }
}

🔑 核心作用:强制子类实现特定行为,确保接口一致性。


2、继承和重写

继承(Inheritance) 是面向对象的重要特性,允许一个类(子类)基于另一个类(父类)进行扩展,复用其字段和方法。

首先定义一个基类 Animal

class Animal {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
  speak() {
    console.log(`${this.name} makes a sound.`);
  }
}

再创建子类 Dog 继承 Animal,并重写(override) speak 方法:

class Dog extends Animal {
  breed: string;
  constructor(name: string, breed: string) {
    super(name); // 调用父类构造函数
    this.breed = breed;
  }
  speak() {
    console.log(`${this.name} barks!`);
  }
}

测试结果表明,子类成功继承了父类的字段,并覆盖了其方法行为:

在这里插入图片描述

运行输出验证了多态性:

在这里插入图片描述

🔄 重写 vs 重载

  • 重写(Override):子类重新定义父类的同名方法(签名相同),实现多态;
  • 重载(Overload):同一类中多个同名但参数不同的方法(前文已介绍)。

💡 super 关键字:在子类构造函数中必须先调用 super(...) 初始化父类部分;在方法中可用 super.method() 调用父类版本。


通过以上内容,您已系统掌握 ArkTS 中类与对象的核心机制:从字段、方法、构造函数,到抽象类、继承与多态。这些是构建复杂鸿蒙应用架构的基石。后续可结合 接口(Interface)泛型(Generics)装饰器(Decorators) 进一步提升代码的灵活性与可维护性。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐