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