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(),重写方法要保持参数与返回类型兼容,才能写出既灵活又不失控的类体系。