摘要:概述和對(duì)比接口和類在實(shí)際使用中,一般都是配合使用的。接口是一個(gè)對(duì)外的協(xié)商約定。我們先實(shí)現(xiàn)一個(gè)交通工具的抽象類,然后繼承實(shí)現(xiàn)輪船類。我們可以發(fā)現(xiàn)抽象類已經(jīng)實(shí)現(xiàn)的方法,子類是無(wú)需重復(fù)實(shí)現(xiàn)的。
概述和對(duì)比
接口和類在實(shí)際使用中,一般都是配合使用的。我們來(lái)對(duì)比一下:
接口可以聲明一個(gè)類的結(jié)構(gòu),包含屬性和方法,但它只是給出一個(gè)聲明,沒有訪問(wèn)修飾符,沒有具體的方法實(shí)現(xiàn),沒有構(gòu)造函數(shù),也不可以被實(shí)例化。
接口是一個(gè)對(duì)外的協(xié)商、約定。繼承后才可以實(shí)例化,繼承的時(shí)候必須實(shí)現(xiàn)聲明。可以多重繼承。
類是也是聲明一個(gè)類的結(jié)構(gòu),包含屬性和方法,有訪問(wèn)修飾符,有具體的方法實(shí)現(xiàn),有構(gòu)造函數(shù),可以實(shí)例化(抽象類下面說(shuō))。繼承的時(shí)候,可以覆蓋,也可以繼承使用父類實(shí)現(xiàn)。
抽象類也是類,不過(guò)它可以包含接口類似的特性:普通方法包含實(shí)現(xiàn),抽象方法是不包含實(shí)現(xiàn)的;抽象類不能實(shí)例化。繼承后才可以實(shí)例化,繼承的時(shí)候必須實(shí)現(xiàn)抽象聲明,其他聲明和普通類一樣。
補(bǔ)充說(shuō)明一下,這里的接口、類與純正的面向?qū)ο笳Z(yǔ)言Java比,有一些不同的地方,有興趣的可以自行了解。接口與類的使用場(chǎng)景
這里將給一個(gè)稍微復(fù)雜一點(diǎn)的例子:旅行社運(yùn)送旅客。
定義接口這里我們定義了幾類接口:旅客、載客、位置、運(yùn)送,目的就是聲明規(guī)范,實(shí)現(xiàn)了這些接口的類就可以被用來(lái)做這些事情。
// 旅客 interface Passgener { name: string; } // 載客 interface Carriable { passengers: Passgener[]; getUp (...passengers: Passgener[]): number; getOff (): number; } // 位置 interface Positioned { x: number; y: number; } // 常量:初始位置 const positionOrigin: Positioned = { x: 0, y: 0 }; // 運(yùn)送 interface Moveable { position: Positioned; moveTo(Positioned: Positioned): Positioned; }實(shí)現(xiàn)具體類
這里我實(shí)現(xiàn)了兩個(gè)類:小汽車、巴士,這兩個(gè)類均實(shí)現(xiàn)了載客、運(yùn)送接口,也就是說(shuō)明它們是擁有這些能力的。
// 小汽車 class Car implements Carriable, Moveable { passengers: Passgener[]; position: Positioned; capacity: number; constructor(capacity: number) { this.passengers = []; this.position = positionOrigin; this.capacity = capacity; } getUp (...passengers: Passgener[]): number { if (passengers.length > this.capacity) { throw new Error(`This car can carry ${this.capacity} passengers!`); } console.log( `This car carries ${passengers.map(item => item.name).join(",")}` ); return this.passengers.push(...passengers); } getOff (): number { return this.passengers.splice(0).length; } moveTo(position: Positioned): Positioned { Object.assign(this.position, position); console.log( `This car carries ${this.passengers.map(item => item.name).join(",")} to [${ this.position.x }, ${this.position.y}]` ); return this.position; } } // 巴士 class Bus implements Carriable, Moveable { passengers: Passgener[]; position: Positioned; capacity: number; constructor(capacity: number) { this.passengers = []; this.position = positionOrigin; this.capacity = capacity; } getUp (...passengers: Passgener[]): number { if (passengers.length > this.capacity) { throw new Error(`This Bus can carry ${this.capacity} passengers!`); } console.log( `This Bus carries ${passengers.map(item => item.name).join(",")}` ); return this.passengers.push(...passengers); } getOff (): number { return this.passengers.splice(0).length; } moveTo(position: Positioned): Positioned { Object.assign(this.position, position); console.log( `This Bus carries ${this.passengers.map(item => item.name).join(",")} to [${ this.position.x }, ${this.position.y}]` ); return this.position; } }實(shí)現(xiàn)功能
具體類定義出來(lái)了,我們就可以實(shí)現(xiàn)功能,我們定義一個(gè)旅行社,由旅行社來(lái)運(yùn)送旅客。
// 旅行社 class TravelAgency { name: string; constructor(name: string) { this.name = name; } carrying (carrier: Carriable & Moveable, position: Positioned, ...passengers: Passgener[]): Positioned { carrier.getUp(...passengers); return carrier.moveTo(position); } } // 實(shí)例化對(duì)象 let t1 = new TravelAgency("t1"); let c1 = new Car(4); let b1 = new Bus(30); // 實(shí)現(xiàn)功能 t1.carrying(c1, {x: 10, y: 60}, {name: "Jack"}, {name: "Tom"}); t1.carrying(b1, {x: 10, y: 60}, {name: "Jack"}, {name: "Tom"}, {name: "Mary"}, {name: "Joe"});抽象類的使用場(chǎng)景
上面已經(jīng)把完整的功能實(shí)現(xiàn)出來(lái)了,但是我們可以看到,Car和Bus的代碼還是有冗余的。這里我們就可以通過(guò)抽象類來(lái)做一些優(yōu)化。
我們先實(shí)現(xiàn)一個(gè)交通工具的抽象類,然后繼承實(shí)現(xiàn)輪船類。我們可以發(fā)現(xiàn)抽象類已經(jīng)實(shí)現(xiàn)的方法,子類是無(wú)需重復(fù)實(shí)現(xiàn)的。只有抽象出來(lái)的必須子類實(shí)現(xiàn)的才需要實(shí)現(xiàn)。
// 交通工具 abstract class Vehicle implements Carriable, Moveable { name: string; passengers: Passgener[]; position: Positioned; capacity: number; // 抽象方法 abstract run(speed: number): void; getUp (...passengers: Passgener[]): number { if (passengers.length > this.capacity) { throw new Error(`This ${this.name} can carry ${this.capacity} passengers!`); } console.log( `This ${this.name} carries ${passengers.map(item => item.name).join(",")}` ); return this.passengers.push(...passengers); } getOff (): number { return this.passengers.splice(0).length; } moveTo(position: Positioned): Positioned { Object.assign(this.position, position); console.log( `This ${this.name} carries ${this.passengers.map(item => item.name).join(",")} to [${ this.position.x }, ${this.position.y}]` ); return this.position; } } // 輪船 class Ship extends Vehicle { constructor(capacity: number) { super(); this.passengers = []; this.position = positionOrigin; this.capacity = capacity; } // 抽象方法必須實(shí)現(xiàn) run(speed: number) { // todo, run as a ship... console.log(`This ${this.name} running at ${speed}km/h.`); } }
到此介紹完了接口和類的基本使用場(chǎng)景,再次體會(huì)一下關(guān)鍵字:抽象、繼承。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/110300.html
摘要:使用場(chǎng)景數(shù)據(jù)類型聲明和約束聲明數(shù)據(jù)類型使用數(shù)據(jù)類型面向?qū)ο缶幊踢@里和面向?qū)ο笳Z(yǔ)言類似,用于定義對(duì)象接口,聲明對(duì)象的結(jié)構(gòu),定義類時(shí)可以實(shí)現(xiàn)接口,滿足這個(gè)接口定義的功能。 什么是接口 TypeScript的核心就是類型檢查,接口就是用于聲明類型,給內(nèi)部或第三方使用者提供類型聲明和約束。 使用場(chǎng)景 數(shù)據(jù)類型聲明和約束 // 聲明數(shù)據(jù)類型 interface CustomerInfo { ...
摘要:靜態(tài)屬性靜態(tài)方法目前支持靜態(tài)方法表示,類屬性及靜態(tài)屬性目前作為提案還未正式成為標(biāo)準(zhǔn)。在中,抽象類不能用來(lái)實(shí)例化對(duì)象,主要做為其它派生類的基類使用。不同于接口,抽象類可以包含成員的實(shí)現(xiàn)細(xì)節(jié)。中也是這樣規(guī)定的抽象類不允許直接被實(shí)例化。 嘗試重寫 在此之前,通過(guò)《JavaScript => TypeScript 入門》已經(jīng)掌握了類型聲明的寫法。原以為憑著那一條無(wú)往不利的規(guī)則,就可以開開心心的...
摘要:值得注意的是,的返回值復(fù)寫了原始的構(gòu)造函數(shù),原因是類裝飾器必須返回一個(gè)構(gòu)造器函數(shù)。原始構(gòu)造函數(shù)的原型被復(fù)制給的原型,以確保在創(chuàng)建一個(gè)的新實(shí)例時(shí),操作符如愿以償,具體原因可參考鄙人另一篇文章原型與對(duì)象。 上一篇文章中,我們討論了TypeScript源碼中關(guān)于方法裝飾器的實(shí)現(xiàn),搞明白了如下幾個(gè)問(wèn)題: 裝飾器函數(shù)是如何被調(diào)用的? 裝飾器函數(shù)參數(shù)是如何傳入的? __decorate函數(shù)干了...
摘要:前言是面對(duì)對(duì)象的語(yǔ)言,因此有必要單獨(dú)紀(jì)錄下對(duì)象的各種定義和理解。面對(duì)對(duì)象基本概述概述是基于面向過(guò)程的變成思想,是對(duì)面向過(guò)程的一種封裝。面對(duì)對(duì)象開發(fā)就是不斷的創(chuàng)建對(duì)象,使用對(duì)象,指揮對(duì)象做事情。面對(duì)對(duì)象設(shè)計(jì)其實(shí)就是在管理和維護(hù)對(duì)象之間的關(guān)系。 前言 java是面對(duì)對(duì)象的語(yǔ)言,因此有必要單獨(dú)紀(jì)錄下對(duì)象的各種定義和理解。 面對(duì)對(duì)象,主要包括:面向?qū)ο笏枷耄惻c對(duì)象及其使用,對(duì)象的內(nèi)存圖,成...
摘要:本文從裝飾模式出發(fā),聊聊中的裝飾器和注解。該函數(shù)的函數(shù)名。不提供元數(shù)據(jù)的支持。中的元數(shù)據(jù)操作可以通過(guò)包來(lái)實(shí)現(xiàn)對(duì)于元數(shù)據(jù)的操作。 ??隨著Typescript的普及,在KOA2和nestjs等nodejs框架中經(jīng)常看到類似于java spring中注解的寫法。本文從裝飾模式出發(fā),聊聊Typescipt中的裝飾器和注解。 什么是裝飾者模式 Typescript中的裝飾器 Typescr...
閱讀 2679·2021-11-18 10:02
閱讀 3411·2021-09-28 09:35
閱讀 2591·2021-09-22 15:12
閱讀 749·2021-09-22 15:08
閱讀 3086·2021-09-07 09:58
閱讀 3469·2021-08-23 09:42
閱讀 731·2019-08-30 12:53
閱讀 2081·2019-08-29 13:51