1. 程式人生 > >TypeScript躬行記(3)——類

TypeScript躬行記(3)——類

  類是對物件的抽象,描述了物件的特徵和行為,而物件就是類的例項。ES6引入了類的概念(相關內容可參考ES類和ES6類的繼承兩節),TypeScript在此基礎上,不僅根據ES7等規範完善了類的語法,還添加了許多其它語法。而在使用TypeScript的類時,不必關心相容性問題,因為這些工作已由編譯器完成。

  下面是一個簡單的類,包含3個成員:帶private修飾符的name屬性、建構函式constructor()和getName()方法,最後一句使用new運算子建立了Person類的例項,並呼叫了一次它的建構函式。

class Person {
  private name: string;
  constructor(name: string) {
    this.name = name;
  }
  getName() {
    return this.name;
  }
}
let worker = new Person("strick");

  編譯後的程式碼如下所示,通過傳統的建構函式和基於原型的繼承來模擬一個類。

var Person = /** @class */ (function() {
  function Person(name) {
    this.name = name;
  }
  Person.prototype.getName = function() {
    return this.name;
  };
  return Person;
})();
var worker = new Person("strick");

一、屬性

  在ES6中,例項屬性(即自有屬性)得作為this物件的屬性存在,並且一般都會在建構函式中執行初始化,而TypeScript允許在類中直接定義例項屬性,如下所示。

class Person {
  constructor(name: string) {
    this.name = name;
  }
}
//TypeScript中的例項屬性
class Person {
  name: string;
}

  不僅如此,TypeScript還提供了存在於類本身上的靜態屬性,即不需要例項化就能呼叫的屬性。在下面的示例中,為age屬性添加了static關鍵字,使其成為靜態屬性,通過類的名稱就能直接呼叫它。

class Person {
  static age: number;
}
Person.age = 28;

二、修飾符

  修飾符是用於限定成員或型別的一種符號,TypeScript包含三個訪問修飾符:public、private和protected,以及一個成員修飾符:readonly。

1)public

  在TypeScript中,成員預設都是public的,即在派生類(也叫子類)或類的外部都能被訪問。在下面的示例中,Person類中的name屬性是公共的,Programmer類繼承了Person類。注意,當派生類包含一個建構函式時,必須呼叫super()方法,執行基類(即父類)的建構函式,並且該方法得在訪問this物件之前呼叫。

class Person {
  public name: string;
  constructor(name: string) {
    this.name = name;
  }
}
class Programmer extends Person {
  constructor(name: string) {
    super(name);
  }
}

  在初始化Person類或Programmer類之後,就能通過建立的例項來訪問name屬性,如下所示。

let person = new Person("strick");
person.name;            //"strick"
let programmer = new Programmer("freedom");
programmer.name;        //"freedom"

2)private

  當成員被修飾為private時,只能在類的內部訪問它,例如在基類Person中宣告一個私有的age屬性,在類的例項或派生類的例項中訪問age屬性都會在編譯階段報錯,如下所示。

class Person {
  private age: number;
}
person.age;            //錯誤
programmer.age;        //錯誤

  當建構函式被修飾為private時(如下所示),包含它的類既不能例項化,也不能被繼承。

class Person {
  private constructor(name: string) {
    this.name = name;
  }
}

3)protected

  此修飾符與private的行為類似,只是有一點不同,即在派生類中還是可以訪問它的,例如在基類Person中宣告一個受保護的school屬性,在派生類中就能訪問到它,如下所示(省略了基類的建構函式)。

class Person {
  protected school: string;
}
class Programmer extends Person {
  constructor(name: string) {
    super(name);
    this.school = "university";
  }
}

  當建構函式被修飾為protected時(如下所示),包含它的類不能例項化,但可以被繼承。

class Person {
  protected constructor(name: string) {
    this.name = name;
  }
}

4)readonly

  當成員被修飾為readonly時,它就變成只讀的,只能在宣告時或建構函式裡初始化,其它地方對它的修改都是禁止的,如下所示。

class Person {
  readonly gender: string = "女";        //正確
  constructor() {
    this.gender = "男";                //正確
  }
}
let person = new Person();
person.gender = "女";                 //錯誤

  當readonly與其它修飾符一起使用時,需跟在它們後面,如下所示。

class Person {
  protected readonly gender: string;
}

三、引數屬性

  引數屬性可以便捷的在建構函式中宣告並初始化一個類的屬性,此類引數會與三個訪問修飾符或readonly組合使用,如下所示。

class Person {
  constructor(public name: string) { }
}

  建構函式中的name是一個引數屬性,相當於在Person類中宣告一個name屬性,並在建構函式中為其初始化,如下所示。

class Person {
  public name: string;
  constructor(name: string) {
    this.name = name;
  }
}

四、抽象類

  抽象類是供其它派生類繼承的基類,它與介面一樣,不能被例項化,但可以包含成員的實現細節。在宣告一個類時,如果包含abstract關鍵字,那麼這就是一個抽象類,如下所示,當對其進行例項化時,會在編譯時報錯。

abstract class Person { }
let person = new Person();        //錯誤

  在抽象類中,會宣告一個或多個帶abstract類修飾符的抽象方法,它們只有名稱,不包含實現細節,可與訪問修飾符組合使用,如下所示。

abstract class Person {
  protected abstract work(): void
}

  派生類中必須實現繼承的抽象方法(如下所示),否則會在編譯階段報錯。

class Programmer extends Person {
  public work(): void {
    console.log("code");
  }
}

&n