classAnimal {constructor(name) {this.name = name; }sayHi() {return`My name is ${this.name}`; }}let a =newAnimal('Jack');console.log(a.sayHi()); // My name is Jack
類別的繼承
使用 extends 關鍵字實現繼承,子類別中使用 super 關鍵字來呼叫父類別的建構函式和方法。
classCatextendsAnimal {constructor(name) {super(name); // 呼叫父類別的 constructor(name)console.log(this.name); }sayHi() {return'Meow, '+super.sayHi(); // 呼叫父類別的 sayHi() }}let c =newCat('Tom'); // Tomconsole.log(c.sayHi()); // Meow, My name is Tom
classAnimal {staticisAnimal(a) {return a instanceofAnimal; }}let a =newAnimal('Jack');Animal.isAnimal(a); // truea.isAnimal(a); // TypeError: a.isAnimal is not a function
classAnimal {public name;publicconstructor(name) {this.name = name; }}let a =newAnimal('Jack');console.log(a.name); // Jacka.name ='Tom';console.log(a.name); // Tom
上面的例子中,name 被設定為了 public,所以直接訪問實例的 name 屬性是允許的。
很多時候,我們希望有的屬性是無法直接存取的,這時候就可以用 private 了:
classAnimal {private name;publicconstructor(name) {this.name = name; }}let a =newAnimal('Jack');console.log(a.name); // Jacka.name ='Tom';// index.ts(9,13): error TS2341: Property 'name' is private and only accessible within class 'Animal'.// index.ts(10,1): error TS2341: Property 'name' is private and only accessible within class 'Animal'.
var Animal = (function () {functionAnimal(name) {this.name = name; }return Animal;}());var a =newAnimal('Jack');console.log(a.name);a.name ='Tom';
使用 private 修飾的屬性或方法,在子類別中也是不允許訪問的:
classAnimal {private name;publicconstructor(name) {this.name = name; }}classCatextendsAnimal {constructor(name) {super(name);console.log(this.name); }}// index.ts(11,17): error TS2341: Property 'name' is private and only accessible within class 'Animal'.
classAnimal {public name;privateconstructor (name) {this.name = name; }}classCatextendsAnimal {constructor (name) {super(name); }}let a =newAnimal('Jack');// index.ts(7,19): TS2675: Cannot extend a class 'Animal'. Class constructor is marked as private.// index.ts(13,9): TS2673: Constructor of class 'Animal' is private and only accessible within the class declaration.
當建構函式修飾為 protected 時,該類別只允許被繼承:
classAnimal {public name;protectedconstructor (name) {this.name = name; }}classCatextendsAnimal {constructor (name) {super(name); }}let a =newAnimal('Jack');// index.ts(13,9): TS2674: Constructor of class 'Animal' is protected and only accessible within the class declaration.
classAnimal {readonly name;publicconstructor(name) {this.name = name; }}let a =newAnimal('Jack');console.log(a.name); // Jacka.name ='Tom';// index.ts(10,3): TS2540: Cannot assign to 'name' because it is a read-only property.
注意如果 readonly 和其他訪問修飾符同時存在的話,需要寫在其後面。
classAnimal {// public readonly name;publicconstructor(publicreadonly name) {this.name = name; }}
抽象類別
abstract 用於定義抽象類別和其中的抽象方法。
什麼是抽象類別?
首先,抽象類別是不允許被實例化的:
abstractclassAnimal {public name;publicconstructor(name) {this.name = name; }publicabstractsayHi();}let a =newAnimal('Jack');// index.ts(9,11): error TS2511: Cannot create an instance of the abstract class 'Animal'.
abstractclassAnimal {public name;publicconstructor(name) {this.name = name; }publicabstractsayHi();}classCatextendsAnimal {publiceat() {console.log(`${this.name} is eating.`); }}let cat =newCat('Tom');// index.ts(9,7): error TS2515: Non-abstract class 'Cat' does not implement inherited abstract member 'sayHi' from class 'Animal'.
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 Animal = (function () {functionAnimal(name) {this.name = name; }return Animal;}());var Cat = (function (_super) {__extends(Cat, _super);functionCat() {_super.apply(this, arguments); }Cat.prototype.sayHi=function () {console.log('Meow, My name is '+this.name); };return Cat;}(Animal));var cat =newCat('Tom');
類別的型別
給類別加上 TypeScript 的型別很簡單,與介面類似:
classAnimal { name:string;constructor(name:string) {this.name = name; }sayHi():string {return`My name is ${this.name}`; }}let a:Animal=newAnimal('Jack');console.log(a.sayHi()); // My name is Jack