總目錄

從C#到TypeScript - 類

在ES6之前Javascript的類都是用function定義的,ES6把類關(guān)鍵字正式加進(jìn)來,雖說其實也還是function,不過代碼可讀性上好了不少。
TypeScript同樣支持class,并且和C#也非常相似,下面來看看:

同C#一樣,由構(gòu)造函數(shù),屬性,方法組成,屬性和方法有三個級別的訪問權(quán)限:private, protected, public,比C#少個internal
不過不同的是C#類的成員默認(rèn)是private,而TypeScript默認(rèn)是public
在類里面所有成員都必須用this來訪問。

class User{    constructor(name: string, pwd: string){        this.name = name;        this.pwd = pwd;
    }

    name: string;    private pwd: string;

    checkLogin(): boolean{        return this.name === 'brook' && this.pwd === '123';
    }
}let u: User = new User('brook', '123');console.info(u.checkLogin()); // trueu.name = 'test';console.info(u.checkLogin()); // false

參數(shù)屬性

上面的User類有兩個成員,而且都是從構(gòu)造函數(shù)賦值的,也就是其實構(gòu)造函數(shù)的參數(shù)就是類的成員,這就是參數(shù)屬性。
類里面的那兩個屬性其實可以不用寫,只要在構(gòu)造函數(shù)的參數(shù)上加上操作限定符,TypeScript就會自動為參數(shù)生成屬性,來重構(gòu)下上面的User。

class User{    constructor(public name: string, private pwd: string){ }

    checkLogin(): boolean{        return this.name === 'brook' && this.pwd === '123';
    }
}

getter/setter

同樣,也有存取器,不過語法和C#不太一樣,寫起來稍麻煩些。
只有get的時候也就變成只讀屬性了。

class User{    private _name: string;    get name(): string{        return this._name;
    }    set name(name: string){        this._name = name;
    }
}

靜態(tài)屬性和方法

上面說的都是實例成員,TypeScript也支持靜態(tài)成員,不用實例化,而是通過類名來訪問。

class User{    static permission = 'user';    static setPermission(p: string){
        User.permission = p;
    }
}console.info(User.permission); // userUser.setPermission('admin');console.info(User.permission); // admin

也同時支持staticreadonly,不過static要放在前面,這樣可以實現(xiàn)單例模式。

class User{    
    static readonly instance = new User();    private constructor(){}

    checkLogin(name: string, pwd: string): boolean{        return name === 'brook' && pwd === '123';
    }
}console.info(User.instance.checkLogin('brook', '123'));

抽象類

這點和C#一樣,都可以用抽象類來把有共同行為抽象出來,關(guān)鍵字都是abstract。
不能實例化,可以包含實現(xiàn),abstract標(biāo)識的方法,繼承類必須實現(xiàn)。
但沒有virtual關(guān)鍵字,不過和Java一樣,可以認(rèn)為是天生虛函數(shù),也不需要override,直接覆蓋也能支持多態(tài)。
繼承類里要調(diào)用父類的函數(shù)需要用super關(guān)鍵字。

abstract class User{
    name: string;
    pwd: string;    abstract checkLogin(): boolean;
    
    checkName(): boolean {        return this.name.indexOf('.') < 0;
    }
}class Admin extends User {
    checkLogin(): boolean {  // 必須實現(xiàn)的抽象方法
        return this.checkName();  
    }

    checkName(): boolean {  // 這里會把User里的checkName覆蓋掉
        return true && super.checkName();
    }
}let user: User;
user = new Admin(); 
user.name = 'brook.shi';console.info(user.checkLogin()); // 同樣有多態(tài),checkLogin里調(diào)用的是Admin的checkName

另外,繼承時還需要注意,如果派生類里有構(gòu)造函數(shù),則構(gòu)造函數(shù)必須要調(diào)用父類的構(gòu)造函數(shù):super()。

兼容性

TypeScript里的類是有兼容性的,這點和C#很不一樣,TypeScript認(rèn)為:只有成員的類型是兼容的,那它們的類型也是兼容的。
不過成員的兼容對于public很寬容,完全不相干的類如果全是public的成員,并且一致就認(rèn)為是兼容的。
但對于privateprotected則只有是繼承的才會被認(rèn)可為兼容。

class Test1{
    name: string;
    pwd: string;

    checkName(): boolean{        return true;
    }
}class Test2{
    name: string;
    pwd: string;

    checkName(): boolean{        return false;
    }
}let t: Test1 = new Test2();console.info(t.checkName());  // false

如果給上面的TestTest2各加一個private email: string;,結(jié)果是編譯不了,因為它們并不是繼承關(guān)系,也就兼容不了。

泛型

同接口一樣支持泛型,用法也一樣,可以參考接口泛型。

interface Testable<T> {
    field: T;
    method(arg: T): T;
}class Test<T> implements Testable<T>{
    field: T;
    method(arg: T): T{        console.info(`arg is ${typeof arg}`);        return null;
    }
}let test11 = new Test<string>();
test11.method('method');  // arg is stringtest11.method(123); // error, 123 is not string

總的來說,TypeScript的類和C#或Java可以說十分相似,除了兼容性基本上沒有什么新的東西,不過對于JavaScript來說卻是一大進(jìn)步了。

http://www.cnblogs.com/brookshi/p/6395724.html