类和多态

对于传统的 JavaScript 程序我们会使用函数基于原型的继承来创建可重用的组件,但对于熟悉使用面向对象方式的程序员使用这些语法就有些棘手,因为他们用的是基于类的继承并且对象是由类构建出来的。 从 ECMAScript 2015,也就是 ES6 开始, JavaScript 程序员将能够使用基于类的面向对象的方式。 使用 TypeScript,我们允许开发者现在就使用这些特性,并且编译后的 JavaScript 可以在所有主流浏览器和平台上运行,而不需要等到下个 JavaScript 版本。

基本示例

下面看一个使用类的例子:

/* 
类的基本定义与使用
*/
class Person {
 //声明属性
 // 注意: 在ts中,类中要声明属性,必须要提前声明
 name:string
 age:number
 
 //构造方法
 constructor(name,age){
   this.name = name
   this.age = age
}

 //一般方法
 speak():void{
   console.log(`我的名字是${this.name},我的年龄是${this.age}`)
}

}
//创建类的实例
const person1 = new Person('tom',19)
//调用实例的方法
person1.speak()

如果你使用过 C# 或 Java,你会对这种语法非常熟悉。 我们声明一个 Person 类。这个类有 4个成员:一个叫做 name 的属性,一个叫做 age 的属性,一个构造函数和一个 speak 方法。

你会注意到,我们在引用任何一个类成员的时候都用了 this。 它表示我们访问的是类的成员。

后面一行,我们使用 new 构造了 Person 类的一个实例。它会调用之前定义的构造函数,创建一个 Person 类型的新对象,并执行构造函数初始化它。

最后一行通过 person1 对象调用其 speak 方法

继承

在 TypeScript 里,我们可以使用常用的面向对象模式。 基于类的程序设计中一种最基本的模式是允许使用继承来扩展现有的类。

看下面的例子:

class Animal {
 run (distance: number) {
   console.log(`动物奔跑了${distance}米`)
}
}

class Dog extends Animal {
 cry () {
   console.log('汪汪汪!')
}
}

const dog = new Dog()
dog.cry()
dog.run(100) // 可以调用从父中继承得到的方法

这个例子展示了最基本的继承:类从基类中继承了属性和方法。 这里,Dog 是一个 派生类,它派生自 Animal 基类,通过 extends 关键字。 派生类通常被称作子类,基类通常被称作超类

因为 Dog 继承了 Animal 的功能,因此我们可以创建一个 Dog 的实例,它能够 cry()run()

多态

多态指同一个实体同时具有多种形式。它是面向对象程序设计(OOP)的一个重要特征。如果一个语言只支持类而不支持多态,只能说明它是基于对象的,而不是面向对象的,

简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针

下面我们来看个更加复杂的例子:

//定义Animal基类
class Animal {
 //声明属性
 name:string

 //构造方法
 constructor(name){
   this.name = name
}

 //一般方法
 run (distance: number) {
   console.log(`动物前进了 ${distance}m`)
}
}

class Snake extends Animal{
 //构造方法
 constructor(name){
   super(name)
}
 //重写从父类继承过来的方法
 run(distance:number){
   console.log(`蛇前进了${distance}米`)
}
}

class Horse extends Animal{
 //构造方法
 constructor(name){
   super(name)
}
 //重写从父类继承过来的方法
 run(distance:number){
   console.log(`马奔跑了${distance}米`)
}
 //自己的一般方法
 cry(){
   console.log('hou~hou~')
}
}

// 父类型引用指向子类型的实例 ==> 多态
let tom:Animal  //表示tom这个变量的值,应该是animal实例
tom = new Animal('动物')
tom = new Snake('蟒蛇')
tom.run(100)

tom = new Horse('短腿马')
tom.run(300)

这个例子展示了一些上面没有提到的特性。 这一次,我们使用 extends 关键字创建了 Animal的两个子类:HorseSnake

与前一个例子的不同点是,派生类包含了一个构造函数,它 必须调用 super(),它会执行基类的构造函数。 而且,在构造函数里访问 this 的属性之前,我们 一定要调用 super()。 这个是 TypeScript 强制执行的一条重要规则。

这个例子演示了如何在子类里可以重写父类的方法。Snake类和 Horse 类都创建了 run 方法,它们重写了从 Animal 继承来的 run 方法,使得 run 方法根据不同的类而具有不同的功能。注意,即使 tom 被声明为 Animal 类型,但因为它的值是 Horse,调用 tom.run(34) 时,它会调用 Horse 里重写的方法。

posted @ 2020-09-02 20:22  全情海洋  阅读(396)  评论(0编辑  收藏  举报