给团队做次TypeScript分享(六)—— 类

150 阅读3分钟

class Animal {
  animalName:string;
  constructor(name: string) { this.animalName = name; }
  run(): void{
    console.log('Animal run')
  }
}

class Dog extends Animal {
  constructor(name: string) {
    super(name)
  }
  static dagCreate(){
    console.log('Dog静态')
  }
  run(): void {
      console.log(this.animalName + 'run')
      super.run()
  }
}

class Cat extends Animal {
  constructor(name: string) {
    super(name)
  }
  static catCreate(){
    console.log('Cat静态')
  }
  run(): void {
      console.log(this.animalName + 'run')
      super.run()
  }
}


let d1 = new Dog('小七')
d1.run() // 小七run
         // Animal run

当我们在ts中声明一个类的时候,实际上我们创建了一个构造函数,同时也声明了类的实例的类型

class Animal {
  animalName:string;
  constructor(name: string) { this.animalName = name; }
  run(): void{
    console.log('Animal run')
  }
}

let myAnimal:Animal = new Animal('') // Animal类的实例类型就是Animal

typeof Animal 代表Animal类的类型,也就是构造函数的类型

let OtherAnimal: typeof Animal = Animal

类可以被接口继承

class Animal {
  animalName:string;
  constructor(name: string) { this.animalName = name; }
  run(): void{
    console.log('Animal run')
  }  
}

interface IAnimal extends Animal {
  height: number
}

let myAnimal: IAnimal = {
  animalName: '',
  height: 88,
  run(){}
}

修饰符

public 公共修饰符

在不添加修饰符的情况下,默认就是public,表示公共的,可自由访问

class Animal {
  public animalName:string;
  public constructor(name: string) { this.animalName = name; }
  public run(): void{
    console.log('Animal run')
  }
}

private 私有修饰符

可添加 private 修饰符代表私有,不能在声明它的类外面访问

class Animal {
  private animalName:string;
  constructor(name: string) { this.animalName = name; }
  run(): void{
    console.log('Animal run')
  }
}

class Dog extends Animal {
  constructor(name: string) {
    super(name)
  }
  static dagCreate(){
    console.log('Dog静态')
  }
  run(): void {
      console.log(this.animalName + 'run') // 属性“animalName”为私有属性,只能在类“Animal”中访问。
      super.run()
  }
}

console.log(new Animal('小黑').animalName)  // error, 属性“animalName”为私有属性,只能在类“Animal”中访问。

class Animal {
  private animalName:string;
  constructor(name: string) { this.animalName = name; }
  run(): void{
    console.log('Animal run')
  }
  sayMyName(): void{
    console.log(this.animalName)
  }
}

new Animal('小黑').sayMyName() // 小黑

protected 受保护的修饰符

protected 和 private很像,唯一不同的是 protected成员在派生类中仍然可以访问

class Animal {
  protected animalName:string;
  constructor(name: string) { this.animalName = name; }
  run(): void{
    console.log('Animal run')
  }
  sayMyName(): void{
    console.log(this.animalName)
  }
}

class Dog extends Animal {
  constructor(name: string) {
    super(name)
  }
  static dagCreate(){
    console.log('Dog静态')
  }
  run(): void {
      console.log(this.animalName + 'run') // ok,正常访问
      super.run()
  }
}

console.log(new Animal('小黑').animalName) // error 属性“animalName”受保护,只能在类“Animal”及其子类中访问。
console.log(new Dog('小七').animalName) // error 属性“animalName”受保护,只能在类“Animal”及其子类中访问。

构造函数也可以被标记成 protected。 这意味着这个类不能在包含它的类外被实例化,但是能被继承。

class Animal {
  animalName:string;
  protected constructor(name: string) { this.animalName = name; }
  run(): void{
    console.log('Animal run')
  }
}

class Dog extends Animal {
  constructor(name: string) {
    super(name)
  }
  static dagCreate(){
    console.log('Dog静态')
  }
  run(): void {
      console.log(this.animalName + 'run')
      super.run()
  }
}

let myAnimal = new Animal('小黑') // error,类“Animal”的构造函数是受保护的,仅可在类声明中访问。
let myDog = new Dog('小七') // ok

readonly 只读修饰符

只读属性必须在声明时或构造函数里被初始化。

class Animal {
  readonly animalName:string;
  readonly height: number = 88;
  constructor(name: string, height:number) { this.animalName = name; this.height = height 	}
}
let myAnimal = new Animal('小黑', 100)

myAnimal.animalName = '小红' // error 无法分配到 "animalName" ,因为它是只读属性
myAnimal.height = 60 // error 无法分配到 "height" ,因为它是只读属性

参数属性

可以通过在构造函数参数前面添加一个修饰符来将声明和赋值合并

例如

class Animal {
  constructor(readonly animalName: string, public height:number, private color: string, protected weight: number ) { }
  show(): void{
    console.log(this.color, this.weight)
  }
}

let myAnimal = new Animal('小黑', 100, '黑', 100)

console.log(myAnimal.animalName) // 小黑
console.log(myAnimal.height) // 100
myAnimal.show() // 黑 100

抽象类

抽象类做为其它派生类的基类使用,一般不会实例化。用abstract关键字定义抽象类

抽象类中的抽象方法(abstract 关键字定义的方法)不包含具体实现并且必须在派生类中实现。

抽象方法的语法类似前面的接口实现,定义方法签名但不包含方法体(也就是不能有具体实现),但是抽象方法必须用abstract 关键字定义,并且可以使用修饰符

abstract class AnimalAbstract {
  constructor(public animalName:string) {}
  height:number = 88
  run(){
    console.log('run')
  }
  abstract show(): void
}



class Animal extends AnimalAbstract {
  constructor() {
    super('动物')
  }
  show(): void{
    this.run()
  }
}

let myAnimal = new Animal()

console.log(myAnimal.animalName) // 动物
console.log(myAnimal.height) // 88
myAnimal.show() // run