TypeScript 抽象类

一组相关的类常常共享同一套行为骨架:结构相似、实现不同。抽象类(abstract class)用来搭建这种骨架:它既能提供公共实现,又能用抽象方法强制子类补齐细节,让「继承它的类必然具备某些方法」成为编译期保证。

为什么需要抽象类

没有抽象类时,「子类必须实现某方法」只是口头约定,写漏了要等运行期才暴露。抽象类把约定升级成编译错误:漏实现就直接报错,代码更可靠。

定义抽象类与抽象方法

abstract 修饰的类不能直接 new,只能被继承;抽象方法只有签名、没有方法体:

abstract class Animal {
  constructor(public name: string) {}
  abstract makeSound(): void; // 只有签名,没有实现
}

// new Animal("x"); // 报错:无法创建抽象类的实例

抽象类相当于一份「施工图纸」,规定子类必须实现哪些部分。

子类必须实现抽象方法

继承抽象类的子类必须实现全部抽象方法,漏掉任何一个都会编译报错:

class Dog extends Animal {
  makeSound(): void { // 必须实现,否则编译报错
    console.log(this.name + " 汪汪叫");
  }
}

const dog = new Dog("旺财");
dog.makeSound(); // 输出:旺财 汪汪叫

只要子类还残留未实现的抽象方法,它自己仍被视为抽象类,依然无法实例化。

抽象类里的公共实现

抽象类可以包含普通的具体方法,所有子类直接复用,也可以按需重写:

abstract class Shape {
  abstract area(): number; // 子类各自计算面积
  describe(): string {     // 公共方法,子类共享
    return "面积:" + this.area();
  }
}

class Circle extends Shape {
  constructor(private radius: number) {
    super();
  }
  area(): number {
    return Math.PI * this.radius * this.radius;
  }
}

console.log(new Circle(2).describe()); // 输出:面积:12.566370614359172

子类只需实现 area,describe 这类通用逻辑在抽象类中写一次即可。

抽象类与接口的取舍

两者都能约束结构,侧重点不同:

对比项抽象类接口
具体实现可以有已实现的方法只有签名,由实现类补全
继承数量单继承可被 implements 多个
实例字段可以有只描述成员结构
适用场景强相关的类族共享代码跨类别的能力契约

需要复用代码、保存状态选抽象类;只需要「长什么样」的约定选接口。

小结:抽象类 = 公共实现 + 抽象方法约束,专为搭建类族骨架而生;与接口配合,就能把「代码复用」与「结构约定」拆开管理,让继承体系既灵活又可靠。

笔记加载中…