從C#到TypeScript - 接口


總目錄

從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; // 編譯出錯, readonly

let 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
索引支持兩種:numberstring

//定義一個Dict,key是string,value也是string
interface Dict {
    [key: string] : string;
}

let dict: Dict = { 'key1': 'value1', 'key2': 'value2'};
console.info(dict['key1']); // value1
console.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語言靈活的特性。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM