您的位置:

深入了解 TypeScript 继承

TypeScript 是 Microsoft 发布的一款开源的编程语言,它是 JavaScript 的一个超集,TypeScript 在 JavaScript 基础上添加了可选类型和类等面向对象编程的特性。在 TypeScript 中,类是一个重要的概念,类之间的继承是面向对象编程的一个核心。本篇文章从 TypeScript 继承的各个方面进行详细阐述。

一、继承的基本概念

继承是面向对象编程中的一个基本概念。通过继承,一个类可以派生出一个或多个子类,在子类中可以继承父类的属性和方法,并且还可以扩展自己的属性和方法。在 TypeScript 中,继承的语法与 JavaScript 中的类继承类似,使用 extends 关键字。

class Animal {
  type: string = 'animal';
  eat(food: string): void {
    console.log('eating', food);
  }
}
class Dog extends Animal {
  bark(): void {
    console.log('barking');
  }
}

在上述代码中,Dog 类通过 extends 关键字继承了 Animal 类的属性和方法,同时还增加了自己的 bark 方法。通过继承,Dog 实例化后就可以调用 Animal 中的 eat 方法,也可以调用自己新增的 bark 方法。

二、super 关键字

在子类中,如果要调用父类的属性或方法,可以使用 super 关键字。在子类的 constructor 中,可以通过 super() 调用父类的 constructor,也可以在子类方法中使用 super 调用父类方法。

class Animal {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
}
class Dog extends Animal {
  constructor(name: string) {
    super(name);
  }
  bark(): void {
    console.log('barking');
  }
  eat(food: string): void {
    super.eat(food);
    console.log('dog is eating');
  }
}

在上述代码中,Animal 类有一个 name 属性,并且在 constructor 中接收一个参数,这个参数会给 name 赋值。在 Dog 类中,使用 super(name) 调用了 Animal 的 constructor,相当于给 Dog 的 name 属性赋了值。在 Dog 的 eat 方法中,使用 super.eat(food) 调用了 Animal 的 eat 方法,相当于执行了 Animal 中的 eat 方法,同时又增加了一个输出。

三、类的访问修饰符

在 TypeScript 中,类的属性和方法的访问权限可以通过访问修饰符来控制,访问修饰符包括 public、private 和 protected 三种。

public:表示公共的,可以被任何人访问到,包括类的内部和外部;

private:表示私有的,只可以在类的内部访问,不能在类的外部访问;

protected:表示受保护的,只可以在类的内部和子类中访问,不能在类的外部访问。

class Animal {
  public name: string;
  private age: number;
  protected gender: string;
  constructor(name: string, age: number, gender: string) {
    this.name = name;
    this.age = age;
    this.gender = gender;
  }
  eat(food: string): void {
    console.log(`${this.name} is eating ${food}`);
  }
}
class Dog extends Animal {
  constructor(name: string, age: number, gender: string) {
    super(name, age, gender);
  }
  showAge(): void {
    // 报错,age 是 Animal 的私有属性,不能在子类中访问
    // console.log(`${this.name} is ${this.age} years old`);
    console.log(`${this.name} is ${super.age} years old`);
  }
  showGender(): void {
    console.log(`${this.name} is ${this.gender}`);
  }
}

在上述代码中,Animal 类有三个属性,使用了不同的访问修饰符。在 Dog 类中,调用了 super.age 来访问 Animal 类的 age 属性,由于 age 为 private 修饰符,不能通过 this.age 直接访问。在 showGender 方法中,可以直接访问 Animal 类的 protected 属性 gender。

四、抽象类和抽象方法

抽象类是不能被实例化的类,只能被继承。抽象类可以包含抽象方法,抽象方法必须在子类中被实现,否则会报错。

abstract class Animal {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
  abstract eat(food: string): void;
}
class Dog extends Animal {
  constructor(name: string) {
    super(name);
  }
  eat(food: string): void {
    console.log(`${this.name} is eating ${food}`);
  }
}
const dog = new Dog('Tom');
// 报错,无法实例化抽象类
// const animal = new Animal('Bob');

在上述代码中,Animal 类是一个抽象类,它有一个抽象方法 eat,这个方法必须在子类中实现。在 Dog 类中,实现了 eat 方法,并且可以被实例化。在实例化时,尝试实例化 Animal,会报错,因为 Animal 是一个抽象类,不能被实例化。

五、接口与类的关系

在 TypeScript 中,类可以实现接口,实现接口的类必须实现接口中定义的属性和方法。

interface AnimalInterface {
  name: string;
  eat(food: string): void;
}
class Dog implements AnimalInterface {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
  eat(food: string): void {
    console.log(`${this.name} is eating ${food}`);
  }
}
const dog = new Dog('Tom');

在上述代码中,AnimalInterface 接口定义了两个属性,名称和 eat 方法。然后 Dog 类实现了 AnimalInterface 接口,必须实现接口中定义的属性和方法。在实例化 Dog 时,需要传入一个参数 name,这个参数会给 Dog 的 name 属性赋值。

结束语

本文详细阐述了 TypeScript 继承的各个方面,包括继承的基本概念、super 关键字、类的访问修饰符、抽象类和抽象方法、接口与类的关系等。理解并熟练使用 TypeScript 的继承机制,能够使我们更好地进行面向对象编程,提高开发效率和代码质量。