1. 程式人生 > 其它 >深入Typescript--03-Typescript中的類(努力加餐飯)

深入Typescript--03-Typescript中的類(努力加餐飯)

Typescript中的類

一.TS中定義類

class Pointer{
    x!:number; // 例項上的屬性必須先宣告
    y!:number;
    constructor(x:number,y?:number,...args:number[]){
        this.x = x;
        this.y = y as number;
    }
}
let p = new Pointer(100,200);
  • 例項上的屬性需要先宣告在使用,建構函式中的引數可以使用可選引數和剩餘引數

二.類中的修飾符

  • public修飾符(誰都可以訪問到)
class Animal {
    public name!: string; // 不寫public預設也是公開的
    public age!: number;
    constructor(name: string, age: number) {
        this.name = name;
        this.age = age;
    }
}
class Cat extends Animal {
    constructor(name: string, age: number) {
        super(name, age);
        console.log(this.name,this.age); // 子類訪問
    }
}
let p = new Cat('Tom', 18);
console.log(p.name,p.age); // 外層訪問
class Animal {
    constructor(public name: string, public age: number) {
        this.name = name;
        this.age = age;
    }
}
  • 我們可以通過引數屬性來簡化父類中的程式碼

  • protected修飾符 (自己和子類可以訪問到)

class Animal {
    constructor(protected name: string, protected age: number) {
        this.name = name;
        this.age = age;
    }
}
class Cat extends Animal {
    constructor(name: string, age: number) {
        super(name, age);
        console.log(this.name, this.age)
    }
}
let p = new Cat('Tom', 18);
console.log(p.name,p.age);// 無法訪問
  • private修飾符 (除了自己都訪問不到)
class Animal {
    constructor(private name: string, private age: number) {
        this.name = name;
        this.age = age;
    }
}
class Cat extends Animal {
    constructor(name: string, age: number) {
        super(name, age);
        console.log(this.name, this.age); // 無法訪問
    }
}
let p = new Cat('Tom', 18); 
console.log(p.name,p.age);// 無法訪問
  • readonly修飾符 (僅讀修飾符)
class Animal {
    constructor(public readonly name: string, public age: number) {
        this.name = name;
        this.age = age;
    }
    changeName(name:string){
        this.name = name; // 僅讀屬性只能在constructor中被賦值
    }
}
class Cat extends Animal {
    constructor(name: string, age: number) {
        super(name, age);
    }
}
let p = new Cat('Tom', 18); 
p.changeName('Jerry');


三.靜態屬性和方法

class Animal {
    static type = '哺乳動物'; // 靜態屬性
    static getName() { // 靜態方法
        return '動物類';
    }
    private _name: string = 'Tom';

    get name() { // 屬性訪問器
        return this._name;
    }
    set name(name: string) {
        this._name = name;
    }
}
let animal = new Animal();
console.log(animal.name);
  • 靜態屬性和靜態方法是可以被子類所繼承的

四.Super屬性

class Animal {
    say(message:string){
        console.log(message);
    } 
    static getType(){
        return '動物'
    }
}
class Cat extends Animal {
    say(){ // 原型方法中的super指代的是父類的原型
        super.say('貓貓叫');
    }
    static getType(){ // 靜態方法中的super指代的是父類
        return super.getType()
    }
}
let cat = new Cat();
console.log(Cat.getType())

五.類的裝飾器

  • 簡單來說,就是給一個類,新增一些好用的方法,其他類也能用,寫到原型上面,參考5.1
  • 或者是修飾類裡的一些屬性方法,搞通用的那種函式,用來修飾,節省程式碼,可參考5.2,5.3
  • 還可以修飾函式的引數哇 5.4
  • 裝飾器作用就是為了擴充套件類,擴充套件類中的屬性和方法
  • 只能修飾類,不可以修飾函式,函式有變數提升的問題
  • 裝飾器必須是一個函式
  • 執行=洋蔥模型,先從外層執行,執行完後,從內層倒序執行,一層一層剝開,再一層一層執行


1.裝飾類

function addSay(target:any){
    target.prototype.say = function(){console.log('say')}
}
@addSay
class Person {
    say!:Function
}
let person = new Person
person.say();
  • 裝飾類可以給類擴充套件功能,需要開啟experimentalDecorators:true

2.裝飾類中屬性

// target  是類的原型,,key 是需要修飾的屬性
function toUpperCase(target:any,key:string){
    let value = target[key]; 
    Object.defineProperty(target,key,{ // 原型定義屬性
        get(){
            return value.toUpperCase();
        },
        set(newValue){
            value = newValue
        }
    })
}
function double(target: any, key: string) {
    let value = target[key];
    Object.defineProperty(target, key, {
        get() {
            return value * 2;
        },
        set(newValue) {value = newValue}
    })
}
class Person {
    @toUpperCase
    name: string = 'JiangWen'
	@double
    static age: number = 10;
    getName() {
        return this.name;
    }
}
let person = new Person();
console.log(person.getName(),Person.age)
  • 裝飾屬性可以對屬性的內容進行改寫,裝飾的是例項屬性則target指向類的原型、裝飾的是靜態屬性則target執行類本身~

3.裝飾類中方法

// 設定某些方法屬性是否可用
function noEnum(target:any,key:string,descriptor:PropertyDescriptor){
    console.log(descriptor)
    descriptor.enumerable = false;
}
class Person {
    @toUpperCase
    name: string = 'JiangWen'
    @double
    static age: number = 10;
    @noEnum
    getName() {
        return this.name;
    }
}
let person = new Person();
console.log(person); // getName 不可列舉

4.裝飾引數

function addPrefix(target:any,key:string,paramIndex:number){
    console.log(target,key,paramIndex); // Person.prototype getName  0 
}
class Person {
    @toUpperCase
    name: string = 'JiangWen'
    @double
    static age: number = 10;
    prefix!:string
    @noEnum
    getName(@addPrefix prefix:string) {
        return this.name;
    }
}

六.抽象類

  • 抽象類無法被例項化,只能被繼承,抽象方法不能在抽象類中實現,只能在抽象類的具體子類中實現,而且必須實現。
  • 定義型別時void表示函式的返回值為空
abstract class Animal{
    name!:string;
    abstract speak():void
}
class Cat extends Animal {
    speak(){
        console.log('貓貓叫');
    }
}
class Dog extends Animal{
    speak():string{
        console.log('汪汪叫');
        return 'wangwang'
    }
}