Skip to content

类的继承

继承是面向对象编程的核心概念之一。TypeScript 提供了完整的类继承支持,包括方法重写、super 调用和抽象类。

基本继承#

使用 extends 关键字实现继承:

// TypeScript 5.x
// 基类(父类)
class Animal {
name: string
constructor(name: string) {
this.name = name
}
move(distance: number = 0): void {
console.log(`${this.name} 移动了 ${distance}`)
}
}
// 派生类(子类)
class Dog extends Animal {
breed: string
constructor(name: string, breed: string) {
super(name) // 调用父类构造函数
this.breed = breed
}
bark(): void {
console.log('汪汪!')
}
}
const dog = new Dog('旺财', '柴犬')
dog.move(10) // 旺财 移动了 10 米
dog.bark() // 汪汪!
console.log(dog.name, dog.breed) // 旺财 柴犬

super 关键字#

调用父类构造函数#

子类构造函数必须调用 super()

class Parent {
value: number
constructor(value: number) {
this.value = value
}
}
class Child extends Parent {
extra: string
constructor(value: number, extra: string) {
// 必须在访问 this 之前调用 super
super(value)
this.extra = extra
}
}
// 如果子类没有构造函数,会自动调用 super
class SimpleChild extends Parent {
// 自动生成 constructor(...args) { super(...args) }
}

调用父类方法#

class Animal {
name: string
constructor(name: string) {
this.name = name
}
speak(): void {
console.log(`${this.name} 发出声音`)
}
}
class Cat extends Animal {
speak(): void {
super.speak() // 调用父类方法
console.log('喵喵!')
}
}
const cat = new Cat('咪咪')
cat.speak()
// 咪咪 发出声音
// 喵喵!

方法重写#

子类可以重写父类的方法:

class Shape {
color: string
constructor(color: string) {
this.color = color
}
getArea(): number {
return 0
}
describe(): string {
return `一个 ${this.color} 的图形`
}
}
class Circle extends Shape {
radius: number
constructor(color: string, radius: number) {
super(color)
this.radius = radius
}
// 重写 getArea
getArea(): number {
return Math.PI * this.radius ** 2
}
// 重写 describe
describe(): string {
return `一个 ${this.color} 的圆,半径 ${this.radius}`
}
}
class Rectangle extends Shape {
width: number
height: number
constructor(color: string, width: number, height: number) {
super(color)
this.width = width
this.height = height
}
getArea(): number {
return this.width * this.height
}
describe(): string {
return `一个 ${this.color} 的矩形,${this.width}x${this.height}`
}
}

override 修饰符#

TypeScript 4.3+ 提供 override 关键字,确保方法确实重写了父类方法:

class Base {
greet(): void {
console.log('Hello')
}
}
class Derived extends Base {
override greet(): void {
console.log('Hi')
}
// ❌ 错误:父类没有这个方法
// override nonexistent(): void { }
}
// 在 tsconfig.json 中启用严格检查
// "noImplicitOverride": true

抽象类#

抽象类不能被实例化,只能被继承:

abstract class Vehicle {
abstract brand: string
// 抽象方法:没有实现
abstract start(): void
abstract stop(): void
// 普通方法:有实现
honk(): void {
console.log('Beep!')
}
}
class Car extends Vehicle {
brand = 'Toyota'
start(): void {
console.log(`${this.brand} 启动`)
}
stop(): void {
console.log(`${this.brand} 停止`)
}
}
// const vehicle = new Vehicle(); // ❌ 错误:不能实例化抽象类
const car = new Car()
car.start() // Toyota 启动
car.honk() // Beep!

抽象属性和方法#

abstract class DataSource {
// 抽象属性
abstract name: string
abstract readonly type: string
// 抽象方法
abstract connect(): Promise<void>
abstract disconnect(): Promise<void>
abstract query(sql: string): Promise<unknown[]>
// 抽象 getter
abstract get isConnected(): boolean
// 普通方法
log(message: string): void {
console.log(`[${this.name}] ${message}`)
}
}
class MySQLDataSource extends DataSource {
name = 'MySQL'
readonly type = 'relational'
private connected = false
get isConnected(): boolean {
return this.connected
}
async connect(): Promise<void> {
this.connected = true
this.log('Connected')
}
async disconnect(): Promise<void> {
this.connected = false
this.log('Disconnected')
}
async query(sql: string): Promise<unknown[]> {
this.log(`Executing: ${sql}`)
return []
}
}

多层继承#

class Animal {
name: string
constructor(name: string) {
this.name = name
}
eat(): void {
console.log(`${this.name} is eating`)
}
}
class Mammal extends Animal {
furColor: string
constructor(name: string, furColor: string) {
super(name)
this.furColor = furColor
}
nurse(): void {
console.log(`${this.name} is nursing`)
}
}
class Dog extends Mammal {
breed: string
constructor(name: string, furColor: string, breed: string) {
super(name, furColor)
this.breed = breed
}
bark(): void {
console.log('Woof!')
}
}
const dog = new Dog('Rex', 'brown', 'German Shepherd')
dog.eat() // 来自 Animal
dog.nurse() // 来自 Mammal
dog.bark() // 来自 Dog

继承与访问修饰符#

class Parent {
public publicProp = 'public'
protected protectedProp = 'protected'
private privateProp = 'private'
protected protectedMethod(): void {
console.log('Protected method')
}
private privateMethod(): void {
console.log('Private method')
}
}
class Child extends Parent {
accessProps(): void {
console.log(this.publicProp) // ✅
console.log(this.protectedProp) // ✅
// console.log(this.privateProp); // ❌ 不能访问
this.protectedMethod() // ✅
// this.privateMethod(); // ❌ 不能访问
}
// 可以改变 protected 为 public
public protectedMethod(): void {
super.protectedMethod()
console.log('Extended protected method')
}
}

静态成员继承#

class Base {
static count = 0
static increment(): void {
Base.count++
}
}
class Derived extends Base {
static additionalMethod(): void {
console.log(`Count: ${Derived.count}`) // 继承静态属性
Derived.increment() // 继承静态方法
}
}
Derived.increment()
console.log(Derived.count) // 1

实际应用模式#

模板方法模式#

abstract class DataProcessor {
// 模板方法
process(): void {
this.validate()
this.transform()
this.save()
this.notify()
}
// 抽象步骤:子类必须实现
protected abstract validate(): void
protected abstract transform(): void
protected abstract save(): void
// 可选步骤:有默认实现
protected notify(): void {
console.log('Processing complete')
}
}
class UserDataProcessor extends DataProcessor {
protected validate(): void {
console.log('Validating user data...')
}
protected transform(): void {
console.log('Transforming user data...')
}
protected save(): void {
console.log('Saving user data...')
}
protected notify(): void {
super.notify()
console.log('Sending email notification')
}
}
const processor = new UserDataProcessor()
processor.process()

策略模式基类#

abstract class PaymentStrategy {
abstract name: string
abstract pay(amount: number): Promise<boolean>
formatAmount(amount: number): string {
return `$${amount.toFixed(2)}`
}
}
class CreditCardPayment extends PaymentStrategy {
name = 'Credit Card'
constructor(private cardNumber: string) {
super()
}
async pay(amount: number): Promise<boolean> {
console.log(`Paying ${this.formatAmount(amount)} with ${this.name}`)
return true
}
}
class PayPalPayment extends PaymentStrategy {
name = 'PayPal'
constructor(private email: string) {
super()
}
async pay(amount: number): Promise<boolean> {
console.log(`Paying ${this.formatAmount(amount)} with ${this.name}`)
return true
}
}

常见问题#

🙋 抽象类和接口有什么区别?#

// 接口:纯类型约束,无实现
interface Flyable {
fly(): void
}
// 抽象类:可以有部分实现
abstract class Bird {
abstract fly(): void // 抽象方法
eat(): void {
// 具体实现
console.log('Eating')
}
}
// 类可以实现多个接口,但只能继承一个类
class Sparrow extends Bird implements Flyable {
fly(): void {
console.log('Flying')
}
}

🙋 子类构造函数必须调用 super 吗?#

是的,如果子类有构造函数:

class Parent {
constructor(public value: number) {}
}
class Child extends Parent {
constructor(
value: number,
public extra: string
) {
super(value) // 必须调用
}
}
// 如果没有构造函数,自动继承父类构造函数
class SimpleChild extends Parent {}
const child = new SimpleChild(42)

🙋 如何防止类被继承?#

目前 TypeScript 没有 final 关键字,但可以用技巧实现:

class Final {
private constructor() {} // 私有构造函数
static create(): Final {
return new Final()
}
}
// class Extended extends Final {} // ❌ 无法继承

总结#

特性语法用途
继承class B extends A复用父类代码
super 构造super(args)调用父类构造函数
super 方法super.method()调用父类方法
方法重写override method()覆盖父类方法
抽象类abstract class定义抽象基类
抽象方法abstract method()强制子类实现

下一篇我们将学习类与接口的结合使用,深入理解 implements 的用法。