總目錄
從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
也同時支持static
和readonly
,不過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)為是兼容的。
但對于private
和protected
則只有是繼承的才會被認(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
如果給上面的Test
和Test2
各加一個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