typescript中的类

定义

实现一个拥有构造器且能够被继承的对象,与javascript中的class不一样的地方在于属性方法都有类型定义。

语法

class className { constructor([...arguments]){this.xxx = arguments[xxx]}}

  1. // exp:
  2. class Animal {
  3. static hair:string //
  4. //readonly hasFather:boolean //
  5. public name:string //
  6. protected master:boolean //
  7. private family:Array<string> //
  8. //
  9. constructor(hairStr:string,nameStr:string,master:boolean,family:Array<string>){
  10. Animal.hairStr = hair // 只能被类本身调用
  11. this.nameStr = name
  12. this.master = master
  13. this.family = family
  14. }
  15. birth(){
  16. console.log(`it's name is ${this.name} , it has ${Animale.hair} , and it will be the ${this.master}?"master":"not the master" , it love it's ${this.name}`)
  17. }
  18. }
  19. const Lion:Animal = new Animal('Gold','Ather',true,'son,daughter')
  20. Lion.birth() // ...

关键字

  • readonly

    只读属性必须在构造函数中明确赋值,可以被外部访问以及被子类继承,但不能被更改。

  • static

    静态属性,非必须在构造函数中明确赋值,只能在类本身内部被调用,子类不能继承,而且在被调用的时候不能用this,只能用类本身调用,如 Animal.hair。

  • public

    公共属性,必须在构造函数中明确赋值,可以被外部访问以及被子类继承

  • protected

    受保护的属性,必须在构造函数中明确赋值,可以被子类继承,但不能被外部访问,不能与其他类兼容。

  • private

    私有属性,必须在构造函数中明确赋值,不能被子类继承,不能被外部访问,不能与其他类兼容。

  • constructor

    构造器,只要类被实例化,构造函数都会被默认调用

  • abstract

    抽象类。 抽象类做为其它派生类的基类使用。 它们一般不会直接被实例化。 不同于接口,抽象类可以包含成员的实现细节。 abstract关键字是用于定义抽象类和在抽象类内部定义抽象方法。

abstract class Department {

    constructor(public name: string) {
    }

    printName(): void {
        console.log('Department name: ' + this.name);
    }

    abstract printMeeting(): void; // 必须在派生类中实现
}

class AccountingDepartment extends Department {

    constructor() {
        super('Accounting and Auditing'); // 在派生类的构造函数中必须调用 super()
    }

    printMeeting(): void {
        console.log('The Accounting Department meets each Monday at 10am.');
    }

    generateReports(): void {
        console.log('Generating accounting reports...');
    }
}

let department: Department; // 允许创建一个对抽象类型的引用
department = new Department(); // 错误: 不能创建一个抽象类的实例
department = new AccountingDepartment(); // 允许对一个抽象子类进行实例化和赋值
department.printName();
department.printMeeting();
department.generateReports(); // 错误: 方法在声明的抽象类中不存在

继承

子类不能继承父类的静态属性static以及私有属性private。 而且子类构造器上比父类多余的且非子类本身的属性参数只能在子类构造器内部当作普通参数使用,因为父类不存在这个参数的位置。

语法

class sonXXX extends fatherXXX {
    constructor(ar1,ar2,...){ // 子类的构造器比父类多余的参数无法被`this`或者子类本身获取
        super(ar1,ar2,...)
    }
}

例子

class A extends Te {
    constructor(numA:number,namestr:string,count:number){
        super(numA,namestr) // 比父类多出来的参数count不能被写在super当中,因为父类不存在这个参数的位置
        this.num = numA
        // this.name = namestr // 报错,因为父类Te的属性name是只读属性
        if (count > 0) {
            console.log(true)
        }else{
            // alert(false) // 无法构建,在ts中这里的alert会被当成一个方法!?
            console.log(false)
        }
    }
    getCount(count:number){
        console.log(count)
    }
}
const AA:A = new A(123,'testA',-5)
console.log(AA)
// console.log(AA.count) // 报错,因为子类AA中不存在属性count

把类当做接口使用

类跟接口的区别是: 类在编译并部署之后,代码会存在于线上,而接口只会产生一个抽象的映射关系,并不会生成实际的代码

class Point {
    x: number;
    y: number;
}

interface Point3d extends Point {
    z: number;
}

let point3d: Point3d = {x: 1, y: 2, z: 3};

定义一个范围内的不定值

type RankBy = 'title' | 'dueAt' | 'planAt' | 'completeFlag';

export class UseType {
  rankby:RankBy = 'dueAt' // 此时rankby的值只能是上面定义好的值中的一个,否则会报错。
}