TypeScript 類

TypeScript 類

TypeScript 是面向物件的 JavaScript。

類描述了所建立的物件共同的屬性和方法。

TypeScript 支援面向物件的所有特性,比如 類、介面等。

TypeScript 類定義方式如下:

class class_name { 
    // 類作用域
}

定義類的關鍵字為 class,後面緊跟類名,類可以包含以下幾個模組(類的資料成員):

  • 欄位 ? 欄位是類裡面宣告的變數。欄位表示物件的有關資料。

  • 建構函式 ? 類例項化時呼叫,可以為類的物件分配記憶體。

  • 方法 ? 方法為物件要執行的操作。

例項

建立一個 Person 類:

TypeScript

class Person { }

編譯以上程式碼,得到以下 JavaScript 程式碼:

JavaScript

var Person = /** @class */ (function () { function Person() { } return Person; }());

建立類的資料成員

以下例項我們聲明瞭類 Car,包含欄位為 engine,建構函式在類例項化後初始化欄位 engine。

this 關鍵字表示當前類例項化的物件。注意建構函式的引數名與欄位名相同,this.engine 表示類的欄位。

此外我們也在類中定義了一個方法 disp()。

TypeScript

class Car { // 欄位 engine:string; // 建構函式 constructor(engine:string) { this.engine = engine } // 方法 disp():void { console.log("發動機為 : "+this.engine) } }

編譯以上程式碼,得到以下 JavaScript 程式碼:

JavaScript

var Car = /** @class */ (function () { // 建構函式 function Car(engine) { this.engine = engine; } // 方法 Car.prototype.disp = function () { console.log("發動機為 : " + this.engine); }; return Car; }());

建立例項化物件

我們使用 new 關鍵字來例項化類的物件,語法格式如下:

var object_name = new class_name([ arguments ])

類例項化時會呼叫建構函式,例如:

var obj = new Car("Engine 1")

類中的欄位屬性和方法可以使用 . 號來訪問:

// 訪問屬性
obj.field_name 

// 訪問方法
obj.function_name()

完整例項

以下例項建立來一個 Car 類,然後通過關鍵字 new 來建立一個物件並訪問屬性和方法:

TypeScript

class Car { // 欄位 engine:string; // 建構函式 constructor(engine:string) { this.engine = engine } // 方法 disp():void { console.log("函式中顯示發動機型號 : "+this.engine) } } // 建立一個物件 var obj = new Car("XXSY1") // 訪問欄位 console.log("讀取發動機型號 : "+obj.engine) // 訪問方法 obj.disp()

編譯以上程式碼,得到以下 JavaScript 程式碼:

JavaScript

var Car = /** @class */ (function () { // 建構函式 function Car(engine) { this.engine = engine; } // 方法 Car.prototype.disp = function () { console.log("函式中顯示發動機型號 : " + this.engine); }; return Car; }()); // 建立一個物件 var obj = new Car("XXSY1"); // 訪問欄位 console.log("讀取發動機型號 : " + obj.engine); // 訪問方法 obj.disp();

輸出結果為:

讀取發動機型號 :  XXSY1
函式中顯示發動機型號  :   XXSY1

類的繼承

TypeScript 支援繼承類,即我們可以在建立類的時候繼承一個已存在的類,這個已存在的類稱為父類,繼承它的類稱為子類。

類繼承使用關鍵字 extends,子類除了不能繼承父類的私有成員(方法和屬性)和建構函式,其他的都可以繼承。

TypeScript 一次只能繼承一個類,不支援繼承多個類,但 TypeScript 支援多重繼承(A 繼承 B,B 繼承 C)。

語法格式如下:

class child_class_name extends parent_class_name

例項

類的繼承:例項中建立了 Shape 類,Circle 類繼承了 Shape 類,Circle 類可以直接使用 Area 屬性:

TypeScript

class Shape { Area:number constructor(a:number) { this.Area = a } } class Circle extends Shape { disp():void { console.log("圓的面積: "+this.Area) } } var obj = new Circle(223); obj.disp()

編譯以上程式碼,得到以下 JavaScript 程式碼:

JavaScript

var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var Shape = /** @class */ (function () { function Shape(a) { this.Area = a; } return Shape; }()); var Circle = /** @class */ (function (_super) { __extends(Circle, _super); function Circle() { return _super !== null && _super.apply(this, arguments) || this; } Circle.prototype.disp = function () { console.log("圓的面積: " + this.Area); }; return Circle; }(Shape)); var obj = new Circle(223); obj.disp();

輸出結果為:

圓的面積:  223

需要注意的是子類只能繼承一個父類,TypeScript 不支援繼承多個類,但支援多重繼承,如下例項:

TypeScript

class Root { str:string; } class Child extends Root {} class Leaf extends Child {} // 多重繼承,繼承了 Child 和 Root 類 var obj = new Leaf(); obj.str ="hello" console.log(obj.str)

編譯以上程式碼,得到以下 JavaScript 程式碼:

JavaScript

var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var Root = /** @class */ (function () { function Root() { } return Root; }()); var Child = /** @class */ (function (_super) { __extends(Child, _super); function Child() { return _super !== null && _super.apply(this, arguments) || this; } return Child; }(Root)); var Leaf = /** @class */ (function (_super) { __extends(Leaf, _super); function Leaf() { return _super !== null && _super.apply(this, arguments) || this; } return Leaf; }(Child)); // 多重繼承,繼承了 Child 和 Root 類 var obj = new Leaf(); obj.str = "hello"; console.log(obj.str);

輸出結果為:

hello

繼承類的方法重寫

類繼承後,子類可以對父類的方法重新定義,這個過程稱之為方法的重寫。

其中 super 關鍵字是對父類的直接引用,該關鍵字可以引用父類的屬性和方法。

TypeScript

class PrinterClass { doPrint():void { console.log("父類的 doPrint() 方法。") } } class StringPrinter extends PrinterClass { doPrint():void { super.doPrint() // 呼叫父類的函式 console.log("子類的 doPrint()方法。") } }

編譯以上程式碼,得到以下 JavaScript 程式碼:

JavaScript

var obj = new StringPrinter() obj.doPrint() var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var PrinterClass = /** @class */ (function () { function PrinterClass() { } PrinterClass.prototype.doPrint = function () { console.log("父類的 doPrint() 方法。"); }; return PrinterClass; }()); var StringPrinter = /** @class */ (function (_super) { __extends(StringPrinter, _super); function StringPrinter() { return _super !== null && _super.apply(this, arguments) || this; } StringPrinter.prototype.doPrint = function () { _super.prototype.doPrint.call(this); // 呼叫父類的函式 console.log("子類的 doPrint()方法。"); }; return StringPrinter; }(PrinterClass)); var obj = new StringPrinter(); obj.doPrint();

輸出結果為:

父類的 doPrint() 方法。
子類的 doPrint()方法。

static 關鍵字

static 關鍵字用於定義類的資料成員(屬性和方法)為靜態的,靜態成員可以直接通過類名呼叫。

TypeScript

class StaticMem { static num:number; static disp():void { console.log("num 值為 "+ StaticMem.num) } } StaticMem.num = 12 // 初始化靜態變數 StaticMem.disp() // 呼叫靜態方法

編譯以上程式碼,得到以下 JavaScript 程式碼:

JavaScript

var StaticMem = /** @class */ (function () { function StaticMem() { } StaticMem.disp = function () { console.log("num 值為 " + StaticMem.num); }; return StaticMem; }()); StaticMem.num = 12; // 初始化靜態變數 StaticMem.disp(); // 呼叫靜態方法

輸出結果為:

num 值為 12

instanceof 運算子

instanceof 運算子用於判斷物件是否是指定的型別,如果是返回 true,否則返回 false。

TypeScript

class Person{ } var obj = new Person() var isPerson = obj instanceof Person; console.log("obj 物件是 Person 類例項化來的嗎? " + isPerson);

編譯以上程式碼,得到以下 JavaScript 程式碼:

JavaScript

var Person = /** @class */ (function () { function Person() { } return Person; }()); var obj = new Person(); var isPerson = obj instanceof Person; console.log(" obj 物件是 Person 類例項化來的嗎? " + isPerson);

輸出結果為:

obj 物件是 Person 類例項化來的嗎? true

訪問控制修飾符

TypeScript 中,可以使用訪問控制符來保護對類、變數、方法和構造方法的訪問。TypeScript 支援 3 種不同的訪問許可權。

  • public(預設) : 公有,可以在任何地方被訪問。

  • protected : 受保護,可以被其自身以及其子類和父類訪問。

  • private : 私有,只能被其定義所在的類訪問。

以下例項定義了兩個變數 str1 和 str2,str1 為 public,str2 為 private,例項化後可以訪問 str1,如果要訪問 str2 則會編譯錯誤。

TypeScript

class Encapsulate { str1:string = "hello" private str2:string = "world" } var obj = new Encapsulate() console.log(obj.str1) // 可訪問 console.log(obj.str2) // 編譯錯誤, str2 是私有的

類和介面

類可以實現介面,使用關鍵字 implements,並將 interest 欄位作為類的屬性使用。

以下例項紅 AgriLoan 類實現了 ILoan 介面:

TypeScript

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("利潤為 : "+obj.interest+",抽成為 : "+obj.rebate )

編譯以上程式碼,得到以下 JavaScript 程式碼:

JavaScript

var AgriLoan = /** @class */ (function () { function AgriLoan(interest, rebate) { this.interest = interest; this.rebate = rebate; } return AgriLoan; }()); var obj = new AgriLoan(10, 1); console.log("利潤為 : " + obj.interest + ",抽成為 : " + obj.rebate);

輸出結果為:

利潤為 : 10,抽成為 : 1