標籤:出錯 基礎 cto 傳回值 class user config 多重繼承 title
從C#到TypeScript - 介面
為了更好的抽象出行為和屬性,TypeScript在ES6的基礎上增加了介面interface。
C#也有interface,不過TypeScript的介面還不大一樣,C#裡的介面一般是為類服務,讓類實現介面中定義的方法或屬性。
TypeScript在C#基礎上更進一步,由於JavaScript是門非常靈活的語言,TypeScript作為JavaScript的超集需要保持靈活性,所以介面在TypeScript裡可以脫離具體的類,單獨作為類似契約的存在,介面裡的屬性也並非一定需要實現。
類的介面
這和C#的差不多,描述了公用的成員;不過實現介面文法有點類似於Java,用的是implements。
interface Selectable { isSelected: boolean;}class Control implements Selectable { isSelected : boolean;}
同C#一樣,介面可以多重繼承其他介面,用的是extends。
interface Editable {}interface Deleteable {}interface Changeable extends Editable, Deleteable {}
介面的屬性
介面的屬性可以定義為readonly,這個和C#裡只有get沒有set的屬性有點像,同樣,實現介面的類也不一定需要readonly。
interface Selectable{ readonly isSelected: boolean;}class Control implements Selectable{ isSelected: boolean;}let s: Selectable = { isSelected : true };s.isSelected = false; // 編譯出錯, readonlylet c: Control = { isSelected : true };c.isSelected= false; // 沒問題
另外,介面還支援可選屬性,同C#的可空屬性一樣,用?表示,實現介面的類可以不用實現可選屬性。
interface RequestConfig { url: string; body?: any;}class Request implements RequestConfig { url: string;}
介面不需要類的支援
在C#裡面,介面如果沒有類來實現的話是沒有什麼意義的,但在TypeScript裡不一樣,介面可以單獨使用。
interface RequestConfig { url: string; body?: any;}let config: RequestConfig = {url: ‘www.google.com‘};
這種經常用在函數的參數上面,用來描述具體的參數,把具體的參數放到介面裡,方便操作,也方便重構。
function Request(config: RequestConfig){}
介面除了描述屬性外,還可以用來描述函數,不過一個介面只能描述一個函數,描述時定義好參數和傳回值即可。
從實現上看有點類似於C#的delegate。
interface CheckLogin { (name: string, pwd: string): boolean;}let check: CheckLogin = function(name: string, pwd: string): boolean { return false;}
另外,介面還可以用來描述可索引類型,就有點類似C#的Dictionary。
索引支援兩種:number和string。
//定義一個Dict,key是string,value也是stringinterface Dict { [key: string] : string;}let dict: Dict = { ‘key1‘: ‘value1‘, ‘key2‘: ‘value2‘};console.info(dict[‘key1‘]); // value1console.info(dict[‘key‘]); // undefined
介面繼承類
這在C#中很不可思議,介面居然還可以反過來繼承類,不過對於JavaScript裡來說,靈活方便很重要,所以TypeScript實現了這個功能來快速產生一個介面。
雖說在比較複雜的繼承關係時可能會有用,不過個人認為這個功能還是有點雞肋,因為複雜的繼承通常會引入一些問題如緊耦合,牽一髮而動全身,再加上這個,可能更讓人摸不著頭腦,不如用組合來得好。
介面繼承類時會繼承類中所有的成員,不管是private,protected還是public,只是不包括其實現。
不過繼承了一個類不公開成員的介面只能被該類或該類的子類實現。
class User{ name: string; protected pwd: string = "123";}class Admin extends User{ constructor(n: string, p: string){ super(); this.name = n; this.pwd = p; }}interface UserConfig extends User{ //這裡包含了name和private的pwd}let config: UserConfig = new Admin(‘brook‘, ‘123‘);
泛型
TypeScript是同C#一樣支援泛型的,而且在使用方面也差不多,在介面名後面加上<T>即可。
interface Testable<T> { field: T; (arg: T): T;}
也支援泛型約束,關鍵字是extends。
interface Testable<T extends Object> { field: T; (arg: T): T;}
TypeScript的介面對於C#程式員來說是有點奇怪了,不過用過之後還是發現非常符合JavaScript語言靈活的特性。
從C#到TypeScript - 介面