類和多型
類
對於傳統的 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
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的兩個子類:Horse
和 Snake
。
與前一個例子的不同點是,派生類包含了一個建構函式,它 必須呼叫 super()
,它會執行基類的建構函式。 而且,在建構函式裡訪問 this
的屬性之前,我們 一定要呼叫 super()
。 這個是 TypeScript 強制執行的一條重要規則。
這個例子演示瞭如何在子類裡可以重寫父類的方法。Snake
類和 Horse
類都建立了 run
方法,它們重寫了從 Animal
繼承來的 run
方法,使得 run
方法根據不同的類而具有不同的功能。注意,即使 tom
被宣告為 Animal
型別,但因為它的值是 Horse
,呼叫 tom.run(34)
時,它會呼叫 Horse
裡重寫的方法。