继承是面向对象编程的三大特性之一,它允许子类复用父类的代码,并在此基础上进行扩展。TypeScript 使用
extends关键字实现单继承,子类可以获得父类的所有属性和方法。
子类使用 extends 关键字继承父类,自动获得父类的所有公共成员。
class Animal {
name: string
constructor(name: string) {
this.name = name
}
speak(): void {
console.log(`${this.name} 发出声音`)
}
}
class Cat extends Animal {
meow(): void {
console.log(`${this.name} 喵喵叫`)
}
}
const cat = new Cat("小白")
cat.speak()
cat.meow()
Cat 类继承了 Animal 类,拥有了 name 属性和 speak 方法,同时添加了自己的 meow 方法。
子类构造函数必须调用 super(),这会执行父类的构造函数。super 也可以用来调用父类的方法。
class Vehicle {
brand: string
constructor(brand: string) {
this.brand = brand
}
start(): void {
console.log(`${this.brand} 车辆启动`)
}
}
class Car extends Vehicle {
model: string
constructor(brand: string, model: string) {
super(brand)
this.model = model
}
start(): void {
super.start()
console.log(`${this.brand} ${this.model} 准备出发`)
}
}
const car = new Car("丰田", "凯美瑞")
car.start()
子类构造函数中,super() 必须在访问 this 之前调用。子类方法中使用 super.method() 可以调用父类的同名方法。
子类可以重新定义父类的方法,实现不同的行为。这叫做方法重写。
class Shape {
name: string = "形状"
getArea(): number {
return 0
}
describe(): string {
return `这是一个${this.name},面积是 ${this.getArea()}`
}
}
class Circle extends Shape {
radius: number
constructor(radius: number) {
super()
this.name = "圆形"
this.radius = radius
}
getArea(): number {
return Math.PI * this.radius * this.radius
}
}
class Rectangle extends Shape {
width: number
height: number
constructor(width: number, height: number) {
super()
this.name = "矩形"
this.width = width
this.height = height
}
getArea(): number {
return this.width * this.height
}
}
const circle = new Circle(5)
const rectangle = new Rectangle(10, 20)
console.log(circle.describe())
console.log(rectangle.describe())
Circle 和 Rectangle 都重写了 getArea 方法,各自计算自己的面积。describe 方法继承自父类,但调用的 getArea 是子类的版本。
子类继承父类的属性,可以添加新的属性,也可以重新定义属性类型。
class User {
name: string
email: string
constructor(name: string, email: string) {
this.name = name
this.email = email
}
}
class Admin extends User {
role: string = "管理员"
permissions: string[]
constructor(name: string, email: string, permissions: string[]) {
super(name, email)
this.permissions = permissions
}
hasPermission(permission: string): boolean {
return this.permissions.includes(permission)
}
}
const admin = new Admin("张三", "admin@example.com", ["read", "write", "delete"])
console.log(admin.name)
console.log(admin.role)
console.log(admin.hasPermission("write"))
Admin 类继承了 User 的 name 和 email 属性,添加了 role 和 permissions 属性。
继承可以形成链条,一个类继承另一个类,后者又可以继承其他类。
class Entity {
id: number
constructor(id: number) {
this.id = id
}
}
class Person extends Entity {
name: string
constructor(id: number, name: string) {
super(id)
this.name = name
}
}
class Employee extends Person {
department: string
constructor(id: number, name: string, department: string) {
super(id, name)
this.department = department
}
introduce(): string {
return `我是 ${this.name},工号 ${this.id},在 ${this.department} 工作`
}
}
const emp = new Employee(1001, "李四", "技术部")
console.log(emp.introduce())
Employee 继承 Person,Person 继承 Entity,形成了三层继承链。Employee 实例拥有所有祖先类的属性。
子类实例可以赋值给父类类型的变量,这是多态的基础。
class Animal {
name: string
constructor(name: string) {
this.name = name
}
}
class Dog extends Animal {
breed: string
constructor(name: string, breed: string) {
super(name)
this.breed = breed
}
}
function printAnimal(animal: Animal): void {
console.log(`动物名字: ${animal.name}`)
}
const dog = new Dog("小黑", "拉布拉多")
printAnimal(dog)
const animal: Animal = dog
console.log(animal.name)
Dog 实例可以赋值给 Animal 类型的变量,因为 Dog 是 Animal 的子类型。但反过来不行,父类实例不能赋值给子类类型的变量。
TypeScript 只支持单继承,一个类只能有一个直接父类。如果需要组合多个类的功能,可以使用接口或混入。
interface Flyable {
fly(): void
}
interface Swimmable {
swim(): void
}
class Bird implements Flyable, Swimmable {
fly(): void {
console.log("飞翔")
}
swim(): void {
console.log("游泳")
}
}
通过实现多个接口,可以让一个类具备多种能力,弥补单继承的限制。
继承是代码复用的重要手段,通过 extends 关键字,子类可以获得父类的属性和方法。子类可以添加新成员,也可以重写父类的方法。合理使用继承可以减少代码重复,构建清晰的类层次结构。但要注意避免过深的继承链,保持代码的简洁和可维护性。