TypeScript 作为 JavaScript 的超集,引入了类(Class)的概念,使得开发者能够使用面向对象编程(OOP)的思想来编写更加结构化和可维护的代码。本文将详细介绍 TypeScript 中的类,包括其基本用法、高级特性、以及在实际开发中的应用。

1. 什么是类?

类是面向对象编程的核心概念。它是对象的模板,定义了对象的属性和方法。通过类,开发者可以创建具有相同属性和方法的多个对象实例。

2. 类的基本用法

2.1 定义类

在 TypeScript 中,使用 class 关键字定义类。类可以包含属性和方法。

  1. class Person {
  2. name: string;
  3. age: number;
  4. constructor(name: string, age: number) {
  5. this.name = name;
  6. this.age = age;
  7. }
  8. greet() {
  9. console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
  10. }
  11. }
  12. let john = new Person("John", 30);
  13. john.greet(); // 输出: Hello, my name is John and I am 30 years old.

在上述示例中,定义了一个 Person 类,包含两个属性 nameage,以及一个构造函数和一个方法 greet

2.2 构造函数

构造函数用于创建和初始化类的实例。它是一个特殊的方法,在实例化类时自动调用。

  1. class Car {
  2. make: string;
  3. model: string;
  4. year: number;
  5. constructor(make: string, model: string, year: number) {
  6. this.make = make;
  7. this.model = model;
  8. this.year = year;
  9. }
  10. displayInfo() {
  11. console.log(`Car: ${this.make} ${this.model}, Year: ${this.year}`);
  12. }
  13. }
  14. let myCar = new Car("Toyota", "Corolla", 2021);
  15. myCar.displayInfo(); // 输出: Car: Toyota Corolla, Year: 2021

2.3 参数属性

参数属性是一种简写语法,可以在构造函数的参数中直接声明和初始化成员属性。

  1. class User {
  2. constructor(public username: string, private password: string) {}
  3. displayUsername() {
  4. console.log(`Username: ${this.username}`);
  5. }
  6. }
  7. let user = new User("john_doe", "secure_password");
  8. user.displayUsername(); // 输出: Username: john_doe
  9. // console.log(user.password); // 错误: 属性“password”为私有属性,只能在类“User”中访问

2.4 this 类型

在类的方法中,this 表示当前实例。TypeScript 允许使用 this 类型来实现方法链式调用。

  1. class Calculator {
  2. private value: number = 0;
  3. add(num: number): this {
  4. this.value += num;
  5. return this;
  6. }
  7. subtract(num: number): this {
  8. this.value -= num;
  9. return this;
  10. }
  11. getValue(): number {
  12. return this.value;
  13. }
  14. }
  15. let calc = new Calculator();
  16. let result = calc.add(10).subtract(5).getValue();
  17. console.log(result); // 输出: 5

3. 类的继承和多态

3.1 类的继承

继承是 OOP 的一个重要特性,允许一个类继承另一个类的属性和方法。

  1. class Employee extends Person {
  2. employeeId: number;
  3. constructor(name: string, age: number, employeeId: number) {
  4. super(name, age);
  5. this.employeeId = employeeId;
  6. }
  7. work() {
  8. console.log(`${this.name} is working.`);
  9. }
  10. }
  11. let jane = new Employee("Jane", 28, 1234);
  12. jane.greet(); // 输出: Hello, my name is Jane and I am 28 years old.
  13. jane.work(); // 输出: Jane is working.

3.2 多态

多态是指不同对象对同一操作具有不同的响应方式。可以通过继承和接口实现多态。

  1. class Animal {
  2. speak() {
  3. console.log("Animal makes a sound.");
  4. }
  5. }
  6. class Dog extends Animal {
  7. speak() {
  8. console.log("Dog barks.");
  9. }
  10. }
  11. class Cat extends Animal {
  12. speak() {
  13. console.log("Cat meows.");
  14. }
  15. }
  16. function makeSound(animal: Animal) {
  17. animal.speak();
  18. }
  19. let dog = new Dog();
  20. let cat = new Cat();
  21. makeSound(dog); // 输出: Dog barks.
  22. makeSound(cat); // 输出: Cat meows.

4. 高级特性

4.1 抽象类

抽象类是不能被实例化的类,只能被继承。抽象类可以包含抽象方法,抽象方法没有具体实现,必须在派生类中实现。

  1. abstract class Animal {
  2. abstract speak(): void;
  3. move() {
  4. console.log("Moving...");
  5. }
  6. }
  7. class Dog extends Animal {
  8. speak() {
  9. console.log("Dog barks.");
  10. }
  11. }
  12. let dog = new Dog();
  13. dog.speak(); // 输出: Dog barks.
  14. dog.move(); // 输出: Moving...

4.2 接口

接口是定义对象结构的另一种方式,可以用于实现多继承。类可以实现一个或多个接口。

  1. interface Drivable {
  2. drive(): void;
  3. }
  4. interface Flyable {
  5. fly(): void;
  6. }
  7. class FlyingCar implements Drivable, Flyable {
  8. drive() {
  9. console.log("Driving...");
  10. }
  11. fly() {
  12. console.log("Flying...");
  13. }
  14. }
  15. let car = new FlyingCar();
  16. car.drive(); // 输出: Driving...
  17. car.fly(); // 输出: Flying...

4.3 静态成员

静态成员(属性和方法)属于类而不是类的实例。它们可以使用 static 关键字定义。

  1. class MathUtil {
  2. static PI: number = 3.14;
  3. static calculateArea(radius: number): number {
  4. return this.PI * radius * radius;
  5. }
  6. }
  7. console.log(MathUtil.PI); // 输出: 3.14
  8. console.log(MathUtil.calculateArea(10)); // 输出: 314

4.4 成员存取器

成员存取器用于对类属性进行更精细的控制,包括 gettersetter

  1. class Person {
  2. private _name: string;
  3. constructor(name: string) {
  4. this._name = name;
  5. }
  6. get name(): string {
  7. return this._name;
  8. }
  9. set name(newName: string) {
  10. if (newName) {
  11. this._name = newName;
  12. } else {
  13. console.log("Invalid name");
  14. }
  15. }
  16. }
  17. let person = new Person("John");
  18. console.log(person.name); // 输出: John
  19. person.name = "Jane";
  20. console.log(person.name); // 输出: Jane
  21. person.name = ""; // 输出: Invalid name

4.5 索引签名

索引签名允许定义动态的属性名称和类型。

  1. class Dictionary {
  2. [key: string]: string;
  3. addEntry(key: string, value: string) {
  4. this[key] = value;
  5. }
  6. }
  7. let dict = new Dictionary();
  8. dict.addEntry("hello", "world");
  9. console.log(dict.hello); // 输出: world

4.6 类类型

接口可以用来定义类的类型,使得接口不仅可以描述对象,还可以描述类的构造函数。

  1. interface PersonConstructor {
  2. new (name: string, age: number): PersonInterface;
  3. }
  4. interface PersonInterface {
  5. name: string;
  6. age: number;
  7. greet(): void;
  8. }
  9. class Person implements PersonInterface {
  10. constructor(public name: string, public age: number) {}
  11. greet() {
  12. console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
  13. }
  14. }
  15. function createPerson(ctor: PersonConstructor, name: string, age: number): PersonInterface {
  16. return new ctor(name, age);
  17. }
  18. let john = createPerson(Person, "John", 30);
  19. john.greet(); // 输出: Hello, my name is John and I am 30 years old.

5. 实际应用中的类

在实际开发中,类广泛应用于各种场景,如创建组件、实现业务逻辑、封装数据等。

5.1 创建组件

在前端框架如 Angular 中,类用于定义组件。

  1. import { Component } from '@angular/core';
  2. @Component({
  3. selector: 'app-root',
  4. template: `<h1>Hello, {{ name }}</h1>`
  5. })
  6. export class AppComponent {
  7. name = 'Angular';
  8. }

5.2 实现业务逻辑

类用于封装业务逻辑,使得代码更加模块化和易于维护。

  1. class Order {
  2. constructor(public orderId: number, public customerName: string) {}
  3. calculateTotal(items: { price: number, quantity: number }[]): number {
  4. return items.reduce((total, item) => total + item.price * item.quantity, 0);
  5. }
  6. }
  7. let order = new Order
  8. (1, "John Doe");
  9. let total = order.calculateTotal([{ price: 10, quantity: 2 }, { price: 20, quantity: 1 }]);
  10. console.log(`Total: $${total}`); // 输出: Total: $40

5.3 封装数据

类可以用于封装数据,使得数据访问更加安全和一致。

  1. class User {
  2. private password: string;
  3. constructor(public username: string, password: string) {
  4. this.password = password;
  5. }
  6. checkPassword(password: string): boolean {
  7. return this.password === password;
  8. }
  9. }
  10. let user = new User("john_doe", "secure_password");
  11. console.log(user.checkPassword("secure_password")); // 输出: true

结论

通过本文的介绍,我们深入了解了 TypeScript 中的类及其在面向对象编程中的应用。类是 OOP 的核心概念,通过抽象、封装、继承和多态,使得代码更加模块化、复用性和可维护性。在实际开发中,合理使用 TypeScript 的类及其高级特性,可以显著提高代码的质量和开发效率。