TypeScript是面向?qū)ο蟮腏avaScript。TypeScript支持面向?qū)ο蟮木幊坦δ?,如類,接口等。OOP中的類是用于創(chuàng)建對(duì)象的藍(lán)圖。類封裝了對(duì)象的數(shù)據(jù)。Typescript為這個(gè)名為類的概念提供內(nèi)置支持。JavaScript ES5或更早版本不支持類。TypeScript會(huì)從ES6獲得此功能。
使用class關(guān)鍵字的TypeScript聲明一個(gè)類。語法如下所示:
class class_name { //class scope }
class關(guān)鍵字后跟類名。在命名類時(shí)必須考慮標(biāo)識(shí)符的規(guī)則。
一個(gè)類定義可以包括以下內(nèi)容:
字段 - 字段是在類中聲明的任何變量。字段表示與對(duì)象有關(guān)的數(shù)據(jù)
構(gòu)造函數(shù) - 負(fù)責(zé)為類的對(duì)象分配內(nèi)存
函數(shù) - 函數(shù)表示對(duì)象可以采取的操作。它們有時(shí)也被稱為方法。
這些組件放在一起稱為該類的數(shù)據(jù)成員
考慮TypeScript中的Person類。
class Person { }
在編譯時(shí),它會(huì)生成以下JavaScript代碼:
//Generated by typescript 1.8.10 var Person = (function () { function Person() { } return Person; }());
class Car { //field engine:string; //constructor constructor(engine:string) { this.engine = engine } //function disp():void { console.log("Engine is : "+this.engine) } }
本示例聲明一個(gè)類Car。該類有一個(gè)名為engine的字段。同時(shí),聲明字段時(shí)不使用var關(guān)鍵字。上面的例子聲明為類的構(gòu)造函數(shù)。
構(gòu)造函數(shù)是類的特殊函數(shù),負(fù)責(zé)初始化類的變量。TypeScript使用constructor關(guān)鍵字定義構(gòu)造函數(shù)。構(gòu)造函數(shù)是一個(gè)函數(shù),因此可以參數(shù)化。
this關(guān)鍵字是引用類的當(dāng)前實(shí)例。這里,參數(shù)名稱和類字段的名稱是相同的。因此,為了避免歧義,類的字段以this關(guān)鍵字為前綴。
disp()是一個(gè)簡單的函數(shù)定義。注意,此處不使用function關(guān)鍵字。
在編譯時(shí),它會(huì)生成以下JavaScript代碼:
//Generated by typescript 1.8.10 var Car = (function () { //constructor function Car(engine) { this.engine = engine; } //function Car.prototype.disp = function () { console.log("Engine is : " + this.engine); }; return Car; }());
要?jiǎng)?chuàng)建類的實(shí)例,請使用new關(guān)鍵字后跟類名。語法如下所示:
var object_name = new class_name([ arguments ])
new關(guān)鍵字負(fù)責(zé)實(shí)例化。
表達(dá)式的右邊調(diào)用構(gòu)造函數(shù)。如果參數(shù)化,構(gòu)造函數(shù)應(yīng)該傳遞值。
var obj = new Car("Engine 1")
可以通過對(duì)象訪問類的屬性和函數(shù)。使用“.”點(diǎn)表示法(稱為句點(diǎn))訪問類的數(shù)據(jù)成員。
//accessing an attribute obj.field_name //accessing a function obj.function_name()
class Car { //field engine:string; //constructor constructor(engine:string) { this.engine = engine } //function disp():void { console.log("Function displays Engine is : "+this.engine) } } //create an object var obj = new Car("XXSY1") //access the field console.log("Reading attribute value Engine as : "+obj.engine) //access the function obj.disp()
在編譯時(shí),它會(huì)生成以下JavaScript代碼。
//Generated by typescript 1.8.10 var Car = (function () { //constructor function Car(engine) { this.engine = engine; } //function Car.prototype.disp = function () { console.log("Function displays Engine is : " + this.engine); }; return Car; }()); //create an object var obj = new Car("XXSY1"); //access the field console.log("Reading attribute value Engine as : " + obj.engine); //access the function obj.disp();
上面的代碼的輸出如下:
Reading attribute value Engine as : XXSY1 Function displays Engine is : XXSY1
TypeScript支持繼承的概念。繼承是一種程序從現(xiàn)有的類中創(chuàng)建新類的能力。擴(kuò)展為創(chuàng)建較新類的類稱為父類/超類。新創(chuàng)建的類被稱為子類。
一個(gè)類使用“extends”關(guān)鍵字從另一個(gè)類繼承。子類繼承父類的私有成員和構(gòu)造函數(shù)之外的所有屬性和方法。
class child_class_name extends parent_class_name
然而,TypeScript不支持多重繼承。
class Shape { Area:number constructor(a:number) { this.Area = a } } class Circle extends Shape { disp():void { console.log("Area of the circle: "+this.Area) } } var obj = new Circle(223); obj.disp()
在編譯時(shí),它會(huì)生成以下JavaScript代碼:
//Generated by typescript 1.8.10 var __extends = (this && this.__extends) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; var Shape = (function () { function Shape(a) { this.Area = a; } return Shape; }()); var Circle = (function (_super) { __extends(Circle, _super); function Circle() { _super.apply(this, arguments); } Circle.prototype.disp = function () { console.log("Area of the circle: " + this.Area); }; return Circle; }(Shape)); var obj = new Circle(223); obj.disp();
上面的代碼的輸出如下:
Area of the Circle: 223
上面的例子聲明了一個(gè)類Shape。該類由Circle類擴(kuò)展。既然是類之間的繼承關(guān)系,因此子類(即Car類)獲得對(duì)其父類屬性(即area)的隱式訪問。
繼承可以歸類為:
單個(gè) - 每個(gè)類最多可以從一個(gè)父類擴(kuò)展
多個(gè) - 一個(gè)類可以從多個(gè)類繼承。TypeScript不支持多重繼承。
多級(jí)的 - 下面的例子顯示多級(jí)繼承的工作原理。
class Root { str:string; } class Child extends Root {} class Leaf extends Child {} //indirectly inherits from Root by virtue of inheritance var obj = new Leaf(); obj.str ="hello" console.log(obj.str)
類Leaf通過多級(jí)繼承從Root類和Child類派生屬性。
在編譯時(shí),它會(huì)生成以下JavaScript代碼:
//Generated by typescript 1.8.10 var __extends = (this && this.__extends) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; var Root = (function () { function Root() { } return Root; }()); var Child = (function (_super) { __extends(Child, _super); function Child() { _super.apply(this, arguments); } return Child; }(Root)); var Leaf = (function (_super) { __extends(Leaf, _super); function Leaf() { _super.apply(this, arguments); } return Leaf; }(Child)); var obj = new Leaf(); obj.str = "hello"; console.log(obj.str);
它的輸出如下:
hello
方法重寫是由子類重新定義父類方法的機(jī)制。 以下示例說明了相同的情況:
class PrinterClass { doPrint():void { console.log("doPrint() from Parent called…") } } class StringPrinter extends PrinterClass { doPrint():void { super.doPrint() console.log("doPrint() is printing a string…") } } var obj = new StringPrinter() obj.doPrint()
super關(guān)鍵字用來引用類的直接父級(jí)。關(guān)鍵字可用于引用變量,屬性或方法的超類版本。第13行調(diào)用的doWork()函數(shù)的超類版本。
在編譯時(shí),它會(huì)生成以下JavaScript代碼。
//Generated by typescript 1.8.10 var __extends = (this && this.__extends) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; var PrinterClass = (function () { function PrinterClass() { } PrinterClass.prototype.doPrint = function () { console.log("doPrint() from Parent called…"); }; return PrinterClass; }()); var StringPrinter = (function (_super) { __extends(StringPrinter, _super); function StringPrinter() { _super.apply(this, arguments); } StringPrinter.prototype.doPrint = function () { _super.prototype.doPrint.call(this); console.log("doPrint() is printing a string…"); }; return StringPrinter; }(PrinterClass)); var obj = new StringPrinter(); obj.doPrint();
上面的代碼的輸出如下:
doPrint() from Parent called… doPrint() is printing a string…
static關(guān)鍵字可以應(yīng)用于類的數(shù)據(jù)成員。靜態(tài)變量保留其值,直到程序完成執(zhí)行。靜態(tài)成員由類名引用。
class StaticMem { static num:number; static disp():void { console.log("The value of num is"+ StaticMem.num) } } StaticMem.num = 12 // initialize the static variable StaticMem.disp() // invoke the static method
在編譯時(shí),它會(huì)生成以下JavaScript代碼。
//Generated by typescript 1.8.10 var StaticMem = (function () { function StaticMem() { } StaticMem.disp = function () { console.log("The value of num is" + StaticMem.num); }; return StaticMem; }()); StaticMem.num = 12; // initialize the static variable StaticMem.disp(); // invoke the static method
上面的代碼的輸出如下:
The value of num is 12
如果對(duì)象屬于指定類型,則instanceof運(yùn)算符返回true。
class Person{ } var obj = new Person() var isPerson = obj instanceof Person; console.log(" obj is an instance of Person " + isPerson);
在編譯時(shí),它會(huì)生成以下JavaScript代碼。
//Generated by typescript 1.8.10 var Person = (function () { function Person() { } return Person; }()); var obj = new Person(); var isPerson = obj instanceof Person; console.log(" obj is an instance of Person " + isPerson);
上面的代碼的輸出如下:
obj is an instance of Person True
類可以控制其數(shù)據(jù)成員的其他類成員的可見性。此功能稱為Data Hiding(數(shù)據(jù)隱藏
)或Encapsulation(封裝)。
面向?qū)ο笫褂迷L問修飾符或訪問說明符的概念來實(shí)現(xiàn)封裝的概念。訪問說明符/修飾符定義類的數(shù)據(jù)成員在其定義類之外的可見性。
通過TypeScript支持的訪問修飾符是 -
序號(hào) | 訪問說明符和說明 |
---|---|
1 | public 公共的數(shù)據(jù)成員具有普遍的可訪問性。默認(rèn)情況下,類中的數(shù)據(jù)成員是公共的。 |
2 | private 私有數(shù)據(jù)成員只能在定義這些成員的類中訪問。如果外部類成員嘗試訪問私有成員,則編譯器會(huì)引發(fā)錯(cuò)誤。 |
3 | protected 受保護(hù)的數(shù)據(jù)成員可以由與前者相同的類中的成員訪問,也可以由子類的成員訪問。 |
現(xiàn)在讓我們舉個(gè)例子來看看數(shù)據(jù)隱藏如何工作:
class Encapsulate { str:string = "hello" private str2:string = "world" } var obj = new Encapsulate() console.log(obj.str) //accessible console.log(obj.str2) //compilation Error as str2 is private
該類有兩個(gè)字符串屬性,str1和str2,分別是public和private成員。該類被實(shí)例化。該示例返回一個(gè)編譯時(shí)錯(cuò)誤,因?yàn)樗接袑傩詓tr2在聲明它的類之外訪問。
類還可以實(shí)現(xiàn)接口。
interface ILoan { interest:number } class AgriLoan implements ILoan { interest:number rebate:number constructor(interest:number,rebate:number) { this.interest = interest this.rebate = rebate } } var obj = new AgriLoan(10,1) console.log("Interest is : "+obj.interest+" Rebate is : "+obj.rebate )
AgriLoan類實(shí)現(xiàn)了Loan接口。因此,它現(xiàn)在綁定在類上以包含interest屬性作為其成員。
在編譯時(shí),它會(huì)生成以下JavaScript代碼。
//Generated by typescript 1.8.10 var AgriLoan = (function () { function AgriLoan(interest, rebate) { this.interest = interest; this.rebate = rebate; } return AgriLoan; }()); var obj = new AgriLoan(10, 1); console.log("Interest is : " + obj.interest + " Rebate is : " + obj.rebate);
上面的代碼的輸出如下:
Interest is : 10 Rebate is : 1
更多建議: