TypeScript 类继承与多态

继承与多态是面向对象编程的两大核心特性。继承让新类复用已有类的属性和方法,减少重复代码;多态则让同一段代码作用于不同子类时表现出不同行为。TypeScript 在 class 语法之上加入类型检查,使继承关系更安全、更易维护。

extends 实现继承

用 extends 关键字让子类继承父类,子类自动获得父类的属性和方法:

class Animal {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
  speak(): void {
    console.log(`${this.name} 发出声音`);
  }
}

// Puppy 未定义任何成员,却拥有了 name 属性与 speak 方法
class Puppy extends Animal {}

const dog = new Puppy("旺财");
dog.speak(); // 输出:旺财 发出声音

方法重写与 super

子类可以声明同名方法覆盖父类实现,并用 super.xxx() 调用父类版本:

class Dog extends Animal {
  speak(): void {
    console.log(`${this.name} 汪汪两声`);
    super.speak(); // 调用父类实现,按需使用
  }
}
new Dog("大黄").speak();
// 输出:大黄 汪汪两声
// 输出:大黄 发出声音

class Cat extends Animal {
  speak(): void {
    console.log(`${this.name} 喵喵叫`);
  }
}
new Cat("咪咪").speak(); // 输出:咪咪 喵喵叫

构造函数与 super() 规则

子类一旦自己声明 constructor,必须先在首行调用 super(...),之后才能访问 this:

class Horse extends Animal {
  speed: number;
  constructor(name: string, speed: number) {
    super(name); // 第一行初始化父类部分
    this.speed = speed; // 之后才允许使用 this
  }
  run(): void {
    console.log(`${this.name} 时速 ${this.speed} km`);
  }
}
new Horse("赤兔", 60).run(); // 输出:赤兔 时速 60 km

未声明构造函数的子类会沿用父类的构造函数签名,因此 new Puppy("旺财") 是合法的。

多态

把不同子类对象放进父类类型的数组,调用被重写的方法时由实际类型决定执行哪个实现:

const animals: Animal[] = [new Animal("无名"), new Dog("大黄"), new Cat("咪咪")];

for (const a of animals) {
  a.speak(); // 编译期按 Animal 处理,运行期动态分派
}
// 输出:无名 发出声音
// 输出:大黄 汪汪两声 / 大黄 发出声音
// 输出:咪咪 喵喵叫

小结

继承负责代码复用,多态负责行为扩展。牢记两条规则:子类构造器必须先 super(),重写方法要保持参数与返回类型兼容,才能写出既灵活又不失控的类体系。

笔记加载中…