TypeScript | 类 Class

472 阅读3分钟

类描述了所创建的对象共同的属性和方法。通过 class 关键字声明一个类,主要包含以下模块:

  • 属性
  • 构造函数
  • 方法

属性和方法

使用 class 定义类,使用 constructor 定义构造函数。

通过 new 生成新实例的时候,会自动调用构造函数。

class Animal {
  public name;
  constructor(name) {
      this.name = name;
  }
  sayHi() {
      return `My name is ${this.name}`;
  }
}

let a = new Animal('Jack');
console.log(a.sayHi()); // My name is Jack

存取器

TypeScript支持通过getters/setters来截取对对象成员的访问。 它能帮助你有效的控制对对象成员的访问。

class Animal {
  constructor(name) {
    this.name = name;
  }
  get name() {
    return 'Jack';
  }
  set name(value) {
    console.log('setter: ' + value);
  }
}

let a = new Animal('Kitty'); // setter: Kitty
a.name = 'Tom'; // setter: Tom
console.log(a.name); // Jack

类的继承与重写

使用 extends 关键字实现继承,子类中使用 super 关键字来调用父类的构造函数和方法。这样可以抽出公共部分让子类复用。

重写就是子类可以重新编写父类里边的代码。

class Animal {
    name: string;
    constructor(theName: string) { this.name = theName; }
    move(distanceInMeters: number = 0) {
        console.log(`${this.name} moved ${distanceInMeters}m.`);
    }
}

class Snake extends Animal {
    constructor(name: string) { super(name); }
    move(distanceInMeters = 5) {
        console.log("Slithering...");
        super.move(distanceInMeters);
    }
}

class Horse extends Animal {
    constructor(name: string) { super(name); }
    move(distanceInMeters = 45) {
        console.log("Galloping...");
        super.move(distanceInMeters);
    }
}

let sam = new Snake("Sammy the Python");
let tom: Animal = new Horse("Tommy the Palomino");

sam.move();
tom.move(34);

访问修饰符

public

public 修饰的属性或方法是公有的,在程序类的内部和外部都可以访问。类的成员全部默认为 public

class Animal {
  public name;
  public constructor(name) {
    this.name = name;
  }
}

let a = new Animal('Jack');
console.log(a.name); // Jack
a.name = 'Tom';
console.log(a.name); // Tom

private

private 修饰的属性或方法是私有的,不能在声明它的类的外部访问,只能被类的内部访问,在子类中也不允许访问。

当构造函数修饰为 private 时,该类不允许被继承或者实例化:

protected

protected 修饰的属性或方法是受保护的,只能被类的内部以及类的子类访问。

class Animal {
  protected name; 
  public constructor(name) {
    this.name = name;
  }
}
class Cat extends Animal {
  constructor(name) {
    super(name);
    console.log(this.name); // name 在子类中允许访问
  }
}

当构造函数修饰为 protected 时,该类允许被继承,不允许被实例化:

readonly

通过 readonly 关键字将属性设置为只读的。只读属性必须在声明时或构造函数里被初始化。

静态方法

使用 static 修饰符修饰的方法称为静态方法,它们不需要实例化,而是直接通过类来调用,类的实例无法访问:

静态方法调用同一个类中的其他静态方法,可使用 this 关键字:

class StaticMethodCall {

  static staticMethod() {
      return 'Static method has been called'
  }
  
  //静态方法中的 this 指向类本身,而静态方法也存在于类本身
  //所以可以在静态方法中用 this 访问在同一类中的其他静态方法
  static anotherStaticMethod() {
      return this.staticMethod() + ' from another static method'
  }
}

非静态方法中,不能直接使用 this 关键字来访问静态方法。而要用类本身或者构造函数的属性来调用该方法:

class StaticMethodCall {
  constructor() {
      // 类本身调用
      console.log(StaticMethodCall.staticMethod())

      // 构造函数的属性调用
      console.log(this.constructor.staticMethod())
  }
  static staticMethod() {
      return 'static method has been called.'
  }
}

类指向其构造函数本身,在非静态方法中,this.constructor === StaticMethodCall 为 true

抽象类

abstract 用于定义抽象类、抽象类内部定义抽象方法。

抽象类不允许被实例化,抽象类中的抽象方法必须被子类实现

抽象类中的抽象方法被子类实现后不报错了

把类当做接口使用

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

interface Point3d extends Point {
    z: number;
}

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

总结

  • 类指向其构造函数本身。
  • 静态方法存在于类本身上面而不是类的实例上。
  • 抽象类中的抽象方法不包含具体实现并且必须在派生类中实现。
  • TypeScript 新增了 public、protected、private 等访问修饰符。
  • 子类继承父类时,在其构造函数 constructor() 中不要忘了 super() 方法。

学习链接