TypeScript中的類(lèi)
1.概述
類(lèi)這個(gè)概念基本是所有面向?qū)ο缶幊陶Z(yǔ)言都具有一個(gè)概念,例如Java
、Python
等;在JavaScript
中ES6 之前是沒(méi)有類(lèi)這個(gè)概念的,對(duì)于熟悉面向?qū)ο髞?lái)程序猿來(lái)說(shuō)有些棘手,因?yàn)樗麄冇玫亩际腔陬?lèi)的繼承,對(duì)象也是通過(guò)類(lèi)創(chuàng)建出來(lái)的。在ES6中添加了類(lèi)這個(gè)概念,雖然只是一個(gè)語(yǔ)法糖,但是這就可以讓程序員基于類(lèi)去進(jìn)行操作了。在TS中也是支持類(lèi)這個(gè)概念的。
2.定義一個(gè)簡(jiǎn)單的類(lèi)
在TS中也是使用class關(guān)鍵字來(lái)定義一個(gè)類(lèi),示例代碼如下:
;(function () { // 定義類(lèi) class Person { // 公共屬性,默認(rèn)可以不寫(xiě) public name: string // 構(gòu)造函數(shù) constructor(name: string) { // 初始化name屬性 this.name = name } } // 實(shí)例化類(lèi) const person = new Person('一碗周') console.log(person.name) // 一碗周 })()
上面定義的那個(gè)類(lèi)中具有一個(gè)構(gòu)造函數(shù)和一個(gè)公共屬性name,在類(lèi)實(shí)例化時(shí)調(diào)用了constructor構(gòu)造函數(shù),調(diào)用對(duì)功能屬性進(jìn)行初始化。
上面的寫(xiě)法還有一種簡(jiǎn)寫(xiě)形式,如下所示:
;(function () { class Person { constructor(public name: string) {} } // 實(shí)例化類(lèi) const person = new Person('一碗周') console.log(person.name) // 一碗周 })()
這個(gè)寫(xiě)法等同于上面那個(gè)寫(xiě)法。
3.繼承
在面向?qū)ο蟮木幊陶Z(yǔ)言中,有一個(gè)重要得特征就是繼承。繼承就是基于某個(gè)類(lèi)來(lái)擴(kuò)展現(xiàn)有的類(lèi)。
例如,爸爸在北京有一個(gè)四合院,兒子可以繼承爸爸的四合院,而且還可以自己去買(mǎi)一棟別墅;最終兒子的房產(chǎn)擁有北京的四合院和一棟別墅。
在TS中繼承使用extends關(guān)鍵字,示例代碼如下:
;(function () { // 定義一個(gè)基類(lèi),又稱(chēng)超類(lèi) class Person { // 在基類(lèi)中定義一個(gè)name屬性 constructor(public name: string) {} } // 定義一個(gè)派生類(lèi),又稱(chēng)子類(lèi),繼承于基類(lèi) class Programmer extends Person { constructor(name: string, public hobby: string) { // 通過(guò) super 調(diào)用基類(lèi)的構(gòu)造函數(shù) super(name) } } // 實(shí)例化子類(lèi) const programmer = new Programmer('一碗周', 'coding') console.log(programmer.name, programmer.hobby) // 一碗周 coding })()
如上示例代碼中,Person
稱(chēng)作基類(lèi) ,或者稱(chēng)超類(lèi) ,Programmer
是一個(gè)派生類(lèi) ,或者稱(chēng)子類(lèi) 。
在上面那個(gè)例子中,Programmer
類(lèi)通過(guò)extends
關(guān)鍵字繼承于Person
類(lèi)。子類(lèi)擁有父類(lèi)全部的屬性和方法。
在子類(lèi)的構(gòu)造函數(shù)中,我們必須調(diào)用super()
方法來(lái)執(zhí)行基類(lèi)的構(gòu)造函數(shù),這個(gè)是必須的。
類(lèi)的繼承不僅可以繼承類(lèi),而且還可以在子類(lèi)重寫(xiě)父類(lèi)的屬性或者方法。實(shí)例代碼如下:
// 定義一個(gè) Person類(lèi) class Person { constructor(public name: string) {} // 定義一個(gè)方法 sayMy() { console.log(`我的名字: ${this.name}`) } } // 定義一個(gè) Adult 類(lèi)繼承于 Person 類(lèi) class Adult extends Person { constructor(public age: number) { super('彼岸繁華') } // 重寫(xiě)父類(lèi)方法 sayMy() { console.log(`我的名字: ${this.name} 年齡: ${this.age}`) } } // 定義一個(gè) Programmer 類(lèi)繼承于 Adult 類(lèi) class Programmer extends Adult { constructor(public hobby: string) { super(18) } // 重寫(xiě)父類(lèi)方法 sayMy() { console.log( `我的名字: ${this.name} 年齡: ${this.age} 愛(ài)好: ${this.hobby}` ) } } // 類(lèi)的實(shí)例化 const programmer = new Programmer('coding') programmer.sayMy() // 我的名字: 彼岸繁華 年齡: 18 愛(ài)好: coding
首先我們定義了一個(gè)Person
類(lèi),在類(lèi)中定義了一個(gè)屬性和一個(gè)方法;然后又定義了一個(gè)Adult
類(lèi),這個(gè)類(lèi)繼承于Person類(lèi),并重寫(xiě)了Person
類(lèi)中的方法;最后又定義了一個(gè)Programmer
類(lèi),這個(gè)類(lèi)繼承于Adult
類(lèi),并重寫(xiě)了Adult類(lèi)中的方法,也就是說(shuō)Programmer
類(lèi)擁有Person類(lèi)與Adult類(lèi)中的全部屬性與方法,但是sayMe()方法被重寫(xiě)了兩次,也就是說(shuō)Programmer
類(lèi)擁有3個(gè)屬性和1個(gè)方法。
4.public、private、protected修飾符
public、private、protected修飾符的區(qū)別:
public
:公開(kāi)的,我們可以在類(lèi)中自由的訪問(wèn)類(lèi)中定義的成員。TS默認(rèn)為public
private
:私有的,僅僅可以在類(lèi)中訪問(wèn)定義的成員,在類(lèi)外訪問(wèn)不到protected
:受保護(hù)的,可以在本類(lèi)或者子類(lèi)中訪問(wèn)定義的成員。
示例代碼如下所示:
// 定義一個(gè) Person 類(lèi),其中包含 public 成員 private 成員和 protected 成員。 class Person { public name: string // 約定 私有成員一般采用 _ 開(kāi)頭 private _age: number protected hobby: string // 屬性初始化 constructor(name: string, age: number, hobby: string) { this.name = name this._age = age this.hobby = hobby } sayMy() { console.log(this.name, this._age, this.hobby) } } // 實(shí)例化 Person 類(lèi) const person = new Person('一碗周', 18, 'coding') console.log(person.name) // 一碗周 // 類(lèi)外訪問(wèn)私有成員 拋出異常 // console.log(person._age) // 報(bào)錯(cuò) // 類(lèi)外訪問(wèn)保護(hù)成員 拋出異常 // console.log(person.hobby) // 報(bào)錯(cuò) // private 成員和 protected 成員可以在類(lèi)內(nèi)訪問(wèn) person.sayMy() // 一碗周 18 coding // 定義一個(gè)類(lèi)繼承與 Person 類(lèi) class Programmer extends Person { constructor(name: string, age: number, hobby: string) { super(name, age, hobby) } sayMy() { console.log(this.name) // 一碗周 // 在子類(lèi)不可以訪問(wèn)父類(lèi)的私有成員 // console.log(this._age) // 報(bào)錯(cuò) // 在子類(lèi)可以訪問(wèn)受保護(hù)的成員 console.log(this.hobby) // coding } } // 實(shí)例化 Programmer 類(lèi) const programmer = new Programmer('一碗周', 18, 'coding') programmer.sayMy() // 確保跟其他代碼中的成員沖突 export {}
如上代碼中,我們可以在基類(lèi)中訪問(wèn),公共成員、私有成員和保護(hù)成員,但是我們?cè)陬?lèi)外只能訪問(wèn)公共成員。當(dāng)我們定義一個(gè)子類(lèi)繼承于Person
類(lèi)時(shí),我們可以在子類(lèi)訪保護(hù)成員,但是不能訪問(wèn)私有成員。
4.1getters與setters
類(lèi)中的私有成員和保護(hù)成員我們并不是真的不能讀寫(xiě),在TS中提供了getters
與setters
幫助我們有效的控制對(duì)對(duì)象成員的訪問(wèn)。
示例代碼如下所示:
// 定義一個(gè) Person 類(lèi) class Person { // 約定 私有成員一般采用 _ 開(kāi)頭 private _name: string // 屬性初始化 constructor(name: string) { this._name = name } // 獲取 私有的 _name 屬性值 get getName(): string { return this._name } // 設(shè)置 私有的 _name 屬性值 set setName(name: string) { this._name = name } } // 實(shí)例化類(lèi) const person = new Person('一碗粥') // 通過(guò) getName 的方式獲取 console.log(person.getName) // 一碗粥 // 通過(guò) setName 的方式設(shè)置 _name 的值 person.setName = '一碗周' // 重新獲取 console.log(person.getName) // 一碗周
5.readonly修飾符
我們可以通過(guò) readonly
修飾符將一個(gè)屬性設(shè)置為只讀的。只讀屬性必須在聲明時(shí)或者在構(gòu)造函數(shù)中進(jìn)行初始化。
示例代碼如下所示:
// 定義一個(gè)類(lèi),且具有一個(gè)只讀屬性 class Person { // readonly name: string // 等同于 // public readonly name: string // constructor(name: string) { // this.name = name // } // 或者 constructor(public readonly name: string) {} } // 實(shí)例化 const person = new Person('一碗周') console.log(person.name) // 一碗周 // 修改name的值 // person.name = '一碗周' // 錯(cuò)誤! name 是只讀的.
6.靜態(tài)成員
在 TS 中我們也可以創(chuàng)建靜態(tài)成員,這些屬性或者方法是存在于類(lèi)本身而不是存在于類(lèi)的實(shí)例上。在 TS中定義靜態(tài)成員與ES6中一樣,都是使用static
關(guān)鍵字來(lái)說(shuō)明。
示例代碼如下所示:
class Hero { // 計(jì)數(shù)器 static count = 0 constructor(public name: string) { // 每創(chuàng)建一個(gè)屬性 count ++ ++Hero.count } } // 實(shí)例一個(gè) Hero 類(lèi) const hero1 = new Hero('孫悟空') console.log(Hero.count) // 1 const hero2 = new Hero('哪吒') console.log(Hero.count) // 2
這里我們用靜態(tài)屬性實(shí)現(xiàn)了一個(gè)記錄實(shí)例化幾個(gè)類(lèi)的一個(gè)計(jì)數(shù)器。
7.抽象類(lèi)
想要理解什么是抽象類(lèi),就需要先理解什么是抽象,所謂的抽象就是從眾多的事物中抽取出共同的、本質(zhì)性的特征,而舍棄其非本質(zhì)的特征 。例如蘋(píng)果、香蕉、生梨、葡萄、桃子等,它們共同的特性就是水果。得出水果概念的過(guò)程,就是一個(gè)抽象的過(guò)程。
抽象類(lèi)就是將眾多類(lèi)中具有共同部分的功能抽離出來(lái),單獨(dú)創(chuàng)建一個(gè)類(lèi)作為其他派生類(lèi)的基類(lèi)使用。他們不允許被實(shí)例化,定義抽象類(lèi)使用abstract
關(guān)鍵字。
抽象方法就是只有方法的定義,沒(méi)有方法體,方法體需要在子類(lèi)中進(jìn)行實(shí)現(xiàn)。
示例代碼如下:
// 通過(guò) abstract 關(guān)鍵字 定義一個(gè)抽象類(lèi),該類(lèi)不必進(jìn)行初始化,僅作為基類(lèi)使用 abstract class Department { // 初始化name成員,參數(shù)屬性 constructor(public name: string) {} printName(): void { console.log('部門(mén)名稱(chēng): ' + this.name) } // 抽象方法必須包含 abstract 關(guān)鍵字 abstract printMeeting(): void // 必須在派生類(lèi)中實(shí)現(xiàn) } class AccountingDepartment extends Department { constructor() { super('會(huì)計(jì)部') // 在派生類(lèi)的構(gòu)造函數(shù)中必須調(diào)用super() } printMeeting(): void { console.log('會(huì)計(jì)部是負(fù)責(zé)管錢(qián)的部門(mén)') } } // const department = new Department() // 拋出異常:不能創(chuàng)建一個(gè)抽象類(lèi)的實(shí)例 // 實(shí)例化抽象子類(lèi) const department = new AccountingDepartment() // 調(diào)用抽象類(lèi)中的方法 department.printName() // 部門(mén)名稱(chēng): 會(huì)計(jì)部 // 調(diào)用在派生類(lèi)實(shí)現(xiàn)的抽象方法 department.printMeeting() // 會(huì)計(jì)部是負(fù)責(zé)管錢(qián)的部門(mén)
8.類(lèi)與接口
類(lèi)定義會(huì)創(chuàng)建兩個(gè)東西:類(lèi)的實(shí)例類(lèi)型和一個(gè)構(gòu)造函數(shù),因?yàn)轭?lèi)可以創(chuàng)建出類(lèi)型,這一點(diǎn)與我們之前學(xué)習(xí)的接口類(lèi)似,所以說(shuō)我們可以在使用接口的地方使用類(lèi)。
示例代碼如下所示:
// 定義一個(gè)類(lèi) class Point { x: number y: number } // 定義一個(gè)接口繼承與類(lèi) interface Point3d extends Point { z: number } let point3d: Point3d = { x: 1, y: 2, z: 3 }
類(lèi)可以通過(guò)implement去實(shí)現(xiàn)一個(gè)接口,示例代碼如下:
// 定義接口 interface Eat { eat(food: string): void } interface Run { run(distance: number): void } // 定義類(lèi)實(shí)現(xiàn)接口 class Person implements Eat, Run { eat(food: string): void { console.log(food) } run(distance: number) { console.log(distance) } } export {}
到此這篇關(guān)于TypeScript中的類(lèi)的文章就介紹到這了,更多相關(guān)TypeScript類(lèi)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
有關(guān)JavaScript的10個(gè)怪癖和秘密分享
在本片文章中,作者將向您講述JavaScript中最鮮為人知的秘密。學(xué)習(xí)js的朋友可以參考下。2011-08-08js跨域請(qǐng)求數(shù)據(jù)的3種常用的方法
這篇文章主要介紹了js跨域請(qǐng)求數(shù)據(jù)的3種常用的方法,需要的朋友可以參考下2015-12-127道關(guān)于JS this的面試題,你能答對(duì)幾個(gè)
這篇文章主要給大家介紹了7道關(guān)于JS this的面試題,來(lái)看看你能答對(duì)幾個(gè),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03基于JS實(shí)現(xiàn)飛機(jī)大戰(zhàn)游戲的示例代碼
這篇文章主要為大家詳細(xì)介紹了如何利用JS實(shí)現(xiàn)飛機(jī)大戰(zhàn)游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06JavaScript緩動(dòng)動(dòng)畫(huà)函數(shù)的封裝方法
這篇文章主要為大家詳細(xì)介紹了JavaScript緩動(dòng)動(dòng)畫(huà)函數(shù)的封裝方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11一個(gè)輕量級(jí)的XHTML右鍵菜單[支持IE和firefox]
一個(gè)輕量級(jí)的XHTML右鍵菜單[支持IE和firefox]...2007-01-01Echarts?graph關(guān)系圖的使用入門(mén)級(jí)教程
近期需要使用echarts關(guān)系圖,這里給大家總結(jié)下,這篇文章主要給大家介紹了關(guān)于Echarts?graph關(guān)系圖使用的相關(guān)資料,文中給出了詳細(xì)的代碼介紹,需要的朋友可以參考下2024-01-01