继承
在 TypeScript 里,我们可以使用常用的面向对象模式。 基于类的程序设计中一种最基本的模式是允许使用继承来扩展现有的类。
这个例子展示了最基本的继承:类从基类中继承了属性和方法。 这里,Dog
是一个 派生类,它派生自 Animal
基类,通过 extends
关键字。 派生类通常被称作子类,基类通常被称作超类。
因为 Dog
继承了 Animal
的功能,因此我们可以创建一个 Dog
的实例,它能够 cry()
和 run()
。
下面我们来看个更加复杂的例子。
这个例子展示了一些上面没有提到的特性。 这一次,我们使用 extends
关键字创建了 Animal 的两个子类:Horse
和 Snake
。
与前一个例子的不同点是,派生类包含了一个构造函数,它 必须调用 super()
,它会执行基类的构造函数。 而且,在构造函数里访问 this
的属性之前,我们 一定要调用 super()
。 这个是 TypeScript 强制执行的一条重要规则。
这个例子演示了如何在子类里可以重写父类的方法。Snake
类和 Horse
类都创建了 run
方法,它们重写了从 Animal
继承来的 run
方法,使得 run
方法根据不同的类而具有不同的功能。注意,即使 tom
被声明为 Animal
类型,但因为它的值是 Horse
,调用 tom.run(34)
时,它会调用 Horse
里重写的方法。
class Animal {
name: string
constructor(name: string) {
this.name = name
}
run(distance: number = 0) {
console.log(`${this.name} run ${distance}m`)
}
}
class Snake extends Animal {
constructor(name: string) {
// 调用父类型构造方法
super(name)
}
// 重写父类型的方法
run(distance: number = 5) {
console.log('sliding...')
super.run(distance)
}
}
class Horse extends Animal {
constructor(name: string) {
// 调用父类型构造方法
super(name)
}
// 重写父类型的方法
run(distance: number = 50) {
console.log('dashing...')
// 调用父类型的一般方法
super.run(distance)
}
xxx() {
console.log('xxx()')
}
}
const snake = new Snake('sn')
snake.run()
const horse = new Horse('ho')
horse.run()
// 父类型引用指向子类型的实例 ==> 多态
const tom: Animal = new Horse('ho22')
tom.run()
/* 如果子类型没有扩展的方法, 可以让子类型引用指向父类型的实例 */
const tom3: Snake = new Animal('tom3')
tom3.run()
/* 如果子类型有扩展的方法, 不能让子类型引用指向父类型的实例 */
// const tom2: Horse = new Animal('tom2')
// tom2.run()