博客 / 詳情

返回

TypeScript系列:【3】類

基礎説明

先來看個例子:

class Person {
    name: string;
    constructor(name: string) {
        this.name = name;
    }
    say() {
        return "你好,我是" + this.name;
    }
}

這樣,我們就定義了一個類,包含一個屬性用於保存名稱,一個構造器用於創建的時候設置名稱,方法say用於獲取名稱描述:

let person = new Person("小強");
console.log(person.say());

打印的結果就是:“你好,我是小強”。

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

也就是定義屬性、方法等的訪問權限,下面來具體説明。

public

默認訪問權限就是public,你可以自由的訪問程序裏定義的成員,比如上面的例子和下面的代碼是等價的:

class Person {
    public name: string;
    public constructor(name: string) {
        this.name = name;
    }
    public say() {
        return "你好,我是" + this.name;
    }
}

private

當成員被標記成 private時,它就不能在聲明它的類的外部訪問,比如我們對上面的例子進行改造:

class Person {
    private name: string;
    constructor(name: string) {
        this.name = name;
    }
    say() {
        return "你好,我是" + this.name;
    }
}

var person = new Person('小明');

可以看見,name現在是私有屬性了,那麼下面代碼依舊是可以的:

person.say();

而下面的代碼就不行:

// Property 'name' is private and only accessible within class 'Person'.
person.name;
温馨提示:兩個類如果所有的成員的類型都是兼容的,我們就認為它們的類型是兼容的,可是,比較帶有private或protected成員類型的時候,不只是類型需要相同,並且還需要來自同一份聲明。

protected

和private類似,唯一不同的是,除了可以在聲明它的類的內部訪問,還可以在派生類中訪問:

class Person {
    protected name: string;
    constructor(name: string) {
        this.name = name;
    }
}
    
class ChinaPerson extends Person {
    constructor(name: string) {
        super(name);
    }
    say() {
        return "你好,我是" + this.name + ",我來自中國";
    }
}

let chinaPerson = new ChinaPerson("小茜");

那麼,下面代碼也是可行的:

chinaPerson.say();

readonly修飾符

也就是標記只讀,只讀的屬性只能聲明時或構造函數裏被初始化,例如:

class Person {
    readonly name: string = "小灰灰";
}
    
let person = new Person();

那麼,讀取是可以的:

person.name;

而下面當我們嘗試修改就會出錯:

// Cannot assign to 'name' because it is a read-only property.
person.name = "大灰灰";

參數屬性

如果只讀屬性希望通過構造函數初始化,可以這樣:

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

而更簡單的寫法是:

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

靜態屬性

也就是那些歸屬類而不是對象的屬性或方法,例如:

class Person {
    static age: number;
}

直接使用類即可訪問:

Person.age = 10;

而對象則無法訪問:

// Property 'age' does not exist on type 'Person'. 
// Did you mean to access the static member 'Person.age' instead?ts(2576)
new Person().age = 10;

存取器

比如我們現在有一個場景:

class Person {
    name: string;
}

那麼,我們創建好對象後就可以很容易的設置和獲取屬性name值:

let person = new Person();

person.name = "阿肥";
console.log(person.name);

可是現在有一個問題,name值在設置的時候必須滿足一定規則。怎麼辦?我們就可以把上面的類改寫成使用 getter 和 setter 來實現:

class Person {
    private _name: string;
    
    get name(): string {
        return this._name;
    }
    
    set name(name: string) {
        if (name.length > 4) {
        this._name = name;
        }
    }
}

名稱設置名稱的時候,長度必須大於4,不然會設置失敗。

繼承

比如狗是動物,那麼狗就可以繼承動物上面的一些內容:

class Animal {
    eat() {
        console.log("我會吃飯");
    }
}
    
class Dog extends Animal {
    bark() {
        console.log("我會狗叫");
    }
}

動物的實例上就有eat方法,而狗除了eat還可以bark。

抽象類

和接口類似,只不過可以包含成員的實現細節,abstract關鍵字是用於定義抽象類和在抽象類內部定義抽象方法:

abstract class Dog {
    abstract bark(): void;
    run(): void {
        console.log("我在跑");
    }
}
user avatar chongdianqishi 頭像 joe_sky 頭像 columsys 頭像 zbh 頭像 alfred_5972f8006661f 頭像 iymxpc3k 頭像 shellingfordly 頭像 maogexiaodi 頭像 bbqzhiyoufanshu 頭像 ning_643b67be37ac3 頭像 amap_tech 頭像 yinguangyao 頭像
13 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.