TypeScript真香系列-類

前言

TypeScript真香系列的內容將參考中文文檔,可是文中的例子基本不會和文檔中的例子重複,對於一些地方也會深刻研究。另外,文中一些例子的結果都是在代碼沒有錯誤後編譯爲JavaScript獲得的。若是想實際看看TypeScript編譯爲JavaScript的代碼,能夠訪問TypeScript的在線編譯地址,動手操做,印象更加深入。javascript

類的基礎

TypeScript中的類和ES6中的類十分類似,從下面這個例子就可以看出來了:java

class Man{
    name: string;
    constructor(msg: string) {
        this.name= msg;
    }
    play() {
        return "Hello, " + this.name;
    }
}

let man = new Man("James");
man.name; //"James"
man.play(); //"Hello, James"
複製代碼

咱們在上面聲明瞭一個Man類,類中有三個成員:分別爲name屬性,構造函數,play方法。git

繼承

TypeScript中類的繼承也和ES6中相似,派生類(子類)能夠從基類(父類)中繼承屬性和方法。github

class Man{
    name: string;
    constructor(msg: string) {
        this.name= msg;
    }
    play() {
        return "Hello, " + this.name;
    }
}
class Player extends Man {
    age: string;
    constructor(name: string,age:string) {
        super(name)
        this.age = age;
    }
    showAge() {
        return this.age;
    }
} 

let player = new Player("James","35");
player.age; //"35"
player.name; //"James"
player.play(); //"Hello, James"
複製代碼

在上面的代碼中,Man類就是咱們的基類,Player 類就是咱們的派生類。經過關鍵字extends ,咱們就能夠實現類的繼承。若派生類中包含了構造函數,則必須調用super(),它會執行基類的構造函數。typescript

公共,私有與受保護的修飾符

public

在TypeScript中,成員都是默認標記爲public,能夠理解爲公開,因此咱們能夠自由的訪問程序裏面定義的成員。固然咱們也能夠顯式的標記出來:函數

class Man{
    public name: string;
    public constructor(msg: string) {
        this.name= msg;
    }
    public play() {
        return "Hello, " + this.name;
    }
}
複製代碼

private

咱們能夠把類中的成員標記爲private,能夠理解爲私有的。一旦成員標記標記爲private,咱們就不能在它的類的外部訪問它。ui

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

new Man("James").name; // 錯誤: 'name' 是私有的.
複製代碼

而且在Man的派生類中也是不能訪問的:this

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

class Player extends Man {
    constructor(name: string) {
        super(name);
    }
}

let player = new Player("James");
player.name; //錯誤, 'name' 是私有的.
複製代碼

若是想要訪問Man類中的name,那麼咱們能夠在Man類中定義一個方法show():spa

class Man {
    private name: string;
    constructor(msg: string) {
        this.name = msg;
    }
    show() {
        return this.name;
    }
}

class Player extends Man {
    constructor(name: string) {
        super(name);
    }
}

let player = new Player("James");
plager.show(); //"James"
複製代碼

咱們還能夠用下面這個修飾符來進行相似的操做。code

protected

protected,可理解爲受保護的,和private類似,有一點不一樣的就是,protected成員能夠在派生類中能夠訪問:

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

class Player extends Man {
    constructor(name: string) {
        super(name);
        this.name = name;
    }
    show() {
        return this.name
    }
    
}

let man = new Man("James"); 
man.name; //錯誤, 'name' 是受保護的.
let player = new Player("James");
player.name; //錯誤, 'name' 是受保護的.
player.show(); // "James"
複製代碼

protected固然也能夠標記構造函數。當構造函數被protected標記後,當前類就不能被實例化了,可是能夠被派生類繼承:

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

class Player extends Man {
    constructor(name: string) {
        super(name);
        this.name = name;
    }
}

let man = new Man("James");  //錯誤,Man的構造函數是受保護的
let player = new Player("James");
複製代碼

readonly修飾符

咱們能夠使用readonly將成員設置爲只讀,只讀屬性必須在聲明時或構造函數裏被初始化。

class Man {
    readonly name: string;
    constructor(msg: string) {
        this.name = msg;
    }
}

let man = new Man("James");
man.name = "wade"; //錯誤,name是隻讀屬性
複製代碼

咱們還有另外一種寫法:

class Man {
    constructor(readonly name: string) {
        
    }
}

let man = new Man("James");
複製代碼

對比上面種寫法,發現下面這種方式簡潔了許多,這是咱們使用了參數屬性。參數屬性可讓咱們方便的在一個地方定義並初始化一個成員,並且能夠經過給構造函數前面添加一個訪問限定符(public,private,protected)來進行聲明。以下所示:

//使用前
class Man {
    public name:string
    constructor(name: string) {
        this.name = name
    }
}
//使用後
class Man {
    constructor(public name: string) {
        
    }
}
複製代碼

存取器

在TypeScript中,咱們能夠利用存取器來幫助咱們有效的控制對對象成員的訪問。 首先看沒有存取器的版本:

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

let man = new Man("James");
man.name = "wade";
console.log(man.name); // wade
複製代碼

而後是存取器版本:

class Man {
    public _name: string;
    constructor(msg: string) {
        this._name = msg;
    }
    get myName(): string{
        return this._name;
    }
    set myName(newName: string) {
        this._name = newName;
    }
}

let man = new Man("James");
console.log(man.myName); // James
man.myName = "wade";
console.log(man.myName); // wade
複製代碼

這裏有兩個地方須要注意:一是,存取器要求咱們配置時將編譯器設置爲輸出ECMAScript 5或更高的版本;二是,存取器只帶get不帶set的話,存取器會自動推斷爲readonly。

靜態屬性

TypeScript的靜態屬性和JavaScript中的靜態屬性是相似的。咱們建立的類的靜態成員,這些屬性是在類的自己而不是在類的實例上:

class Man {
    static player: string = "運動員";
    show() {
        return "我職業:" + Man.player
    }
}
let man = new Man();
man.player; //錯誤,player是靜態成員
Man.player; // 運動員
man.show(); // 我職業:運動員
複製代碼

抽象類

TypeScript中的抽象類是提供其餘派生類的基類,可是不能直接被實例化。咱們能夠用abstract關鍵字來定義抽象類和抽象類中的方法。其用法以下:

abstract class Man {

    constructor(public name: string) {
        
    }
    show() {
        return "個人名字:" + this.name
    }

    abstract play(type:string): void; //這個方法必須在派生類中實現,否則派生類就會報錯
}

class Player extends Man {

    constructor(name:string) {
        super(name)   //派生類中的構造函數必須調用super()
    }
    play(type:string) {
        return "個人職業是" + type;
    }
    go() {
        return "沖沖衝";
    }
}
let man: Man;  //能夠建立一個對抽象類的引用
man = new Man("James"); // 錯誤,不能建立一個抽象類的實例
man = new Player("Wade"); //能夠對一個抽象子類進行進行實例化和賦值
man.go();    //錯誤,go方法在聲明的抽象類中不存在
man.play("basketball"); //"個人職業是basketballer"
複製代碼

參考

github.com/zhongsp/Typ…

最後

文中有些地方可能會加入一些本身的理解,如有不許確或錯誤的地方,歡迎指出~ 祝你們新年快樂,闔家辛福! 但願前線的醫護人員健健康康,早日戰勝病毒! 但願你們都健健康康!

相關文章
相關標籤/搜索