Skip to content
On this page

class

TS 中 class 的特点

typescript
class Dog {
  constructor(name: string) {
    this.name = name;
  }
  name: string;

  run() {}
}
1
2
3
4
5
6
7
8
typescript
console.log(Dog.prototype);
// {run: ƒ, constructor: ƒ}

/*
打印出类的原型,
结果是不包含类的成员的, 只有  run(), constructor()
*/
1
2
3
4
5
6
7

成员属性只在实例上, 而不在原型上

typescript
let dog = new Dog("大黄");
console.log(dog);
// Dog {name: "大黄"}

/*
可以看出name属性只在实例上, 而不在原型上
*/
1
2
3
4
5
6
7

实例的属性必须具有初始值,或者在构造函数中被初始化

typescript
let dog = new Dog("大黄");
console.log(dog);
// Dog {name: "大黄"}

/*
可以看出name属性只在实例上, 而不在原型上
*/
1
2
3
4
5
6
7

实例的属性必须具有初始值,或者在构造函数中被初始化

typescript
class Dog1 {
  constructor(name: string) {
    // this.name = name;
  }
  // 错误提示: 属性“name”没有初始化表达式,且未在构造函数中明确赋值。ts(2564)
  name: string;

  run() {}
}
1
2
3
4
5
6
7
8
9

解决

typescript
class Dog1 {
  constructor(name: string) {
    // this.name = name;
  }
  name: string = "dog";

  run() {}
}

// 或者
class Dog2 {
  constructor(name: string) {
    this.name = name;
  }
  name: string;

  run() {}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

类的继承

typescript
class Cat0 extends Dog {
  //错误提示: 派生类的构造函数必须包含 "super" 调用。ts(2377)
  constructor() {}
}
1
2
3
4

解决 super 代表父类的实例

typescript
class Cat extends Dog {
  constructor(name: string, color: string) {
    super(name);
    this.color = color;
  }
  color: string;
}
1
2
3
4
5
6
7

类的成员修饰符

共有成员 -public

类的所有属性默认都是 public,当然也可以直接申明出来

typescript
class Dog1 {
  constructor(name: string) {
    // this.name = name;
  }
  public name: string = "dog";

  run() {}
}
1
2
3
4
5
6
7
8

私有成员 -private

私有成员只能被类本身调用,而不能被类的实例调用,有不能被子类调用

typescript
class Dog {
  constructor(name: string) {
    this.name = name;
  }
  public name: string;

  run() {}

  private walk() {}
}

let dog = new Dog("大黄");

// 错误提示:  属性“walk”为私有属性,只能在类“Dog”中访问。ts(2341)
dog.walk();

class Cat extends Dog {
  constructor(name: string, color: string) {
    super(name);
    this.color = color;
    // 错误提示:  属性“walk”为私有属性,只能在类“Dog”中访问。ts(2341)
    this.walk = () => {};
  }
  color: string;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

可以给构造函数添加私有成员属性,表示该类既不能被实例化,也不能被继承

typescript
class Dog {
  private constructor(name: string) {
    this.name = name;
  }
  public name: string;

  run() {}

  private walk() {}
}
// 错误提示:  类“Dog”的构造函数是私有的,仅可在类声明中访问。ts(2673)
let dog = new Dog("大黄");

// 错误提示:  无法扩展类“Dog”。类构造函数标记为私有。ts(2675)
class Cat extends Dog {
  constructor(name: string, color: string) {
    super(name);
    this.color = color;
  }
  color: string;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

受保护成员 -protect

受保护成员只能在类及其子类中访问, 而不能再类的实例中访问

typescript
class Dog {
  constructor(name: string) {
    this.name = name;
  }
  public name: string;

  protected shout() {}
}

let dog = new Dog("大黄");
// 错误提示: 属性“shout”受保护,只能在类“Dog”及其子类中访问。ts(2445)
dog.shout();

class Cat extends Dog {
  constructor(name: string, color: string) {
    super(name);
    this.color = color;
    // 可以正常访问和执行
    this.shout();
  }
  color: string;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

可以给构造函数添加受保护成员属性,表示该类不能被实例化,只能被继承,相当于申明一个基类

只读属性

只读属性表示不能被更改,并且一定要被初始化

typescript
class Dog {
  constructor(name: string) {
    this.name = name;
  }
  public name: string;

  readonly foots: number = 4;
}
1
2
3
4
5
6
7
8

静态成员 -static

类的静态成员只能通过类名来调用,二不能通过子类调用

typescript
class Dog {
  constructor(name: string) {
    this.name = name;
  }
  public name: string;

  static food = "bones";
}

let dog = new Dog("大黄");
// bones
console.log(Dog.food);
// 错误提示: 属性 "food" 不是类型为 "Dog" 的静态成员ts(2576)
console.log(dog.food);
1
2
3
4
5
6
7
8
9
10
11
12
13
14

类的静态成员也可以被继承

typescript
class Dog {
  constructor(name: string) {
    this.name = name;
  }
  public name: string;

  static food = "bones";
}

class Cat extends Dog {
  constructor(name: string, color: string) {
    super(name);
    this.color = color;
  }
  color: string;
}

// bones
console.log("Cat.food :", Cat.food);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

ES 中并没有抽象类的概念,TS 对此进行了扩展

抽象类

抽象类:只能被继承,不能被实例化的类

typescript
abstract class Animal {
  constructor() {}
}
// 无法创建抽象类的实例。ts(2511)
let animal = new Animal();
1
2
3
4
5

可以在抽象类中定义一个具体的方法并有相关实现 这样子类就可以直接使用,而不用重复实现 --- 实现了方法的复用

typescript
abstract class Animal {
  constructor() {}
  eat() {
    console.log("eat");
  }
}

class Pig extends Animal {
  constructor(name: string) {
    super();
    this.name = name;
  }
  public name: string;

  static food = "bones";
}

let pig = new Pig("佩奇");

pig.eat();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

多态

可以在抽象类中定义一个方法但不具体实现,形成一个抽象方法。抽象方法的好处是可以在子类中有多种方式实现,

typescript
abstract class Animal {
  constructor() {}

  abstract sleep(): void;
}

class Pig extends Animal {
  constructor(name: string) {
    super();
    this.name = name;
  }
  public name: string;

  sleep() {
    console.log("站着睡");
  }
}

let pig = new Pig("佩奇");

pig.sleep();

class Cat extends Animal {
  sleep() {
    console.log("趴着睡");
  }
}
let cat = new Cat();
cat.sleep();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

特殊的 TS 类型:this 类型

类的成员方法可以直接返回一个 this, 这样就可以很方便的实现链式调用

typescript
class WorkFlow {
  step1() {
    return this;
  }
  step2() {
    return this;
  }
}

let workFlow = new WorkFlow();

workFlow.step1().step2();
1
2
3
4
5
6
7
8
9
10
11
12

在继承的时候,this 也可以表现出多态 (this 既可以是父类型,也可以是子类型)

typescript
class WorkFlow {
  step1() {
    return this;
  }
  step2() {
    return this;
  }
}

let workFlow = new WorkFlow();

workFlow.step1().step2();

class MyFlow extends WorkFlow {
  next() {
    return this;
  }
}

let myflow = new MyFlow();

// myflow.next():  MyFlow {}
console.log("myflow.next(): ", myflow.next());

// myflow.next().step1():  MyFlow {}
console.log("myflow.next().step1(): ", myflow.next().step1().next().step2());
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
沪ICP备20006251号-1