TypeSprict — 类

JavaScript 通过构造函数实现类的概念,通过原型链实现继承。而在 ES6 中,我们终于迎来了 class
TypeScript 除了实现了所有 ES6 中的类的功能以外,还添加了一些新的用法。

TS — 类的概念

  1. 类(Class):定义了一件事物的抽象特点,包含它的属性和方法
  2. 对象(Object):类的实例,通过 new 生成
  3. 面向对象(OOP)的三大特性:封装、继承、多态

    • 封装(Encapsulation):将对数据的操作细节隐藏起来,只暴露对外的接口。
    • 继承(Inheritance):子类继承父类,子类除了拥有父类的所有特性外,还有一些更具体的特性。
    • 多态(Polymorphism):由继承而产生了相关的不同的类,对同一个方法可以有不同的响应。
  4. 存取器(getter & setter):用以改变属性的读取和赋值行为

  5. 修饰符(Modifiers):修饰符是一些关键字,用于限定成员或类型的性质。比如 public 表示公有属性或方法
  6. 抽象类(Abstract Class):抽象类是供其他类继承的基类,抽象类不允许被实例化。
    抽象类中的抽象方法必须在子类中被实现
  7. 接口(Interfaces):不同类之间公有的属性或方法,可以抽象成一个接口。
    接口可以被类实现(implements)。一个类只能继承自另一个类,但是可以实现多个接口

创建一个简单的 ts 类

class 定义类,使用 constructor 定义构造函数。通过 new 生成新实例的时候,会自动调用构造函数。

1
2
3
4
5
6
7
8
9
10
11
class Animal {
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
继承

使用 extends 关键字实现继承,子类中使用 super 关键字来调用父类的构造函数和方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Animal {
public name: string;
constructor(name) {
this.name = name;
}
sayHi() {
return `My name is ${this.name}`;
}
}
class Cat extends Animal {
constructor(name: string) {
super(name); // 调用父类的 constructor(name)
}
sayHi() {
return "Meow, " + super.sayHi(); // 调用父类的 sayHi()
}
}

public / private / protected— 公共/私有/受保护的

public — 公共

public‘修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是 ‘public‘的

1
2
3
4
5
6
7
8
9
10
11
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时,它就不能在声明它的类的外部访问,简单的说,只有自己的class内部可以访问,即使是自己的’实例’,’继承的子类’ 都无法访问被’private‘修饰的内容

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
class Animal {
private name: string;
constructor(name: string) {
this.name = name; // 能调用private修饰的
}
public getName() {
return `我的名字${this.name}`; // 能调用private修饰的
}
}

class Cat extends Animal {
constructor(name: string) {
super(name);
}
getTest() {
console.log(this.name); // 错误提示:属性“name”为私有属性,只能在类“Animal ”中访问。
}
}

const dog = new Animal("dog");
// dog.name = "Anne" // 提示错误:属性“name”为私有属性,只能在类“Animal”中访问。
console.log(dog.getName()); // 可以访问,打印结果:我的名字Anne

const cat = new Cat("cat");
// cat.getTest() // 这里是错误的 因为Cat 类也无法使用继承父类的私有属性或者方法

protected — 受保护的

1.修饰的属性或方法是受保护的,它和 private 类似,区别是它在子类中也是允许被访问的,简单的 说’子类是可以访问 protected 修饰的’ 实例是不可以的

2.修饰的是’constructor‘ 则当前类不能创建实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Animal {
protected name: string;
protected constructor(name: string) {
this.name = name;
}
protected getName() {
return this.name;
}
}
//protected 修饰constructor不能创建实例 报错提示:类“Animal”的构造函数是受保护的,仅可在类声明中访问。
// const cat = new Animal (18)

class Dog extends Animal {
constructor(name: string) {
console.log(super.getName()); // 可以访问父类中的protected方法
}
}
const dog = new Dog("Laura");

其他特性

readonly — 只读属性

可以使用 readonly 关键字将属性设置为只读的。

1
2
3
4
5
6
7
8
9
10
class Animal {
readonly name;
public constructor(name) {
this.name = name;
}
}

let a = new Animal("Jack");
console.log(a.name); // Jack
a.name = "Tom"; // 错误 name是只读的

静态属性 — static 修饰

1.’ts‘ 提供了 静态属性,属性和方法都是’static‘ 修饰

2.静态方法没法直接调用类里面的属性,当想要调用类里面的属性的时候需要声明静态的属性

1
2
3
4
5
6
7
8
9
10
class Animal {
public static getName() {
return Animal.name;
}
private static name: string = 18;
constructor() {}
}
const p = new Animal();
// console.log(p.age) // age 是静态的属性 所以实例是不能访问的
// console.log(Animal.age) // 虽然有了类但是也是不能访问的,因为用了private修饰用public可以访问

tsgetter /setter

使用 gettersetter 来改变属性的赋值和读取行为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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

抽象类 abstract

  1. 抽象类是不允许被实例化的
  2. 继承抽象类的类必须去实现实例中的抽象类中的’抽象方法’和’抽象属性’
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
abstract class Animal {
public name;
public constructor(name) {
this.name = name;
}
public abstract sayHi();
}

class Cat extends Animal {
public sayHi() {
// 实现抽象类的抽象方法
console.log(`Meow, My name is ${this.name}`);
}
}
let cat = new Cat("Tom");