# 定义

类(英语: class)在面向对象编程(oop) (opens new window)中是一种面向对象计算机编程语言的构造, 是创建对象的蓝图, 描述了所创建的对象共同的属性和方法。

JavaScript 语言中, 生成实例对象的传统方法是通过构造函数。ES6 提供了更接近传统语言的写法, 引入了 Class(类)这个概念, 作为对象的模板。通过 class 关键字, 可以定义类。

TypeScript 除了实现了所有 ES6 中的类的功能以外,还添加了一些新的用法。

# 类的概念

  • 对象

    类的实例, 通过 new实例化

  • 面向对象三大特性

    👇👇👇 Here

  • 存取器

    getter: 对属性的取值行为

    setter: 对属性的赋值行为

  • 修饰符

    public: 修饰公有属性和方法 (默认),可以在任何地方被访问到

    protected: 修饰保护属性和方法,在子类中也是允许被访问的

    private: 修饰私有属性和方法,不能在声明它的类的外部访问

  • 静态属性 & 方法 static

    只能通过类访问的属性 or 方法。

  • 抽象类

    抽象类(absctract)是供其他类继承的基类,抽象类不允许被实例化。抽象类中的抽象方法必须在子类中被实现

  • 接口

    不同类之间公有的属性或方法,可以抽象成一个接口。接口可以被类实现 (implements)一个类只能继承自另一个类,但是可以实现多个接口

# 面向对象的三大特性

# 封装

利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体,数据被保护在抽象数据类型的内部,尽可能地隐藏内部的细节,只保留一些对外接口使之与外部发生联系。

# 继承

子类获取父类的所有属性和行为(除了父类中用 private 修饰的变量和方法)

# 多态

多种不同的实现方式即为多态, 它允许方法重名,参数或返回值可以是父类型传入或返回。

# 类的好处

# 使用

# public(公有) & protected(保护) & private(私有) 修饰符

# public

修饰公有属性和方法 (默认),可以在任何地方被访问到

class Animal {
    public name: string;
    public constructor(theName: string) { this.name = theName; }
    public move(distanceInMeters: number) {
        console.log(`${this.name} moved ${distanceInMeters}m.`);
    }
}
1
2
3
4
5
6
7

Playground (opens new window)

# protected

修饰保护属性和方法,在子类中也是允许被访问的

class Person {
    protected name: string;
    constructor(name: string) { this.name = name; }
}

class Employee extends Person {
    private department: string;

    constructor(name: string, department: string) {
        super(name)
        this.department = department;
    }

    public getElevatorPitch() {
        return `Hello, my name is ${this.name} and I work in ${this.department}.`;
    }
}

let rainy = new Employee("Rain", "120");
console.log(rainy.getElevatorPitch());
console.log(rainy.name); // 错误
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

Playground (opens new window)

# private

修饰私有属性和方法,不能在声明它的类的外部访问

class Animal {
    private name: string;
    constructor(theName: string) { this.name = theName; }
}

class Cat extends Animal {
    constructor() { super("Cat"); }
}

class Employee {
    private name: string;
    constructor(theName: string) { this.name = theName; }
}

let animal = new Animal("Dog");
let cat = new Cat();
let employee = new Employee("Rain120");

animal = cat;
animal = employee; // 错误: Animal 与 Employee 不兼容.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

Playground (opens new window)

# readonly 修饰符

# 属性

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

class Octopus {
    readonly name: string;
    readonly numberOfLegs: number = 8;
    constructor (theName: string) {
        this.name = theName;
    }
}
let dad = new Octopus("Man with the 8 strong legs");
dad.name = "Man with the 3-piece suit"; // 错误! name 是只读的.
1
2
3
4
5
6
7
8
9

Playground (opens new window)

# 参数

class Octopus {
    readonly numberOfLegs: number = 8;
    constructor(readonly name: string) {
    }
}
1
2
3
4
5

Playground (opens new window)

# 存取器

class Employee {
    private _fullName: string = '';

	constructor(_fullName: string) {}

    get fullName(): string {
        return this._fullName;
    }

    set fullName(newName: string) {
        this._fullName = newName;
    }
}

let employee = new Employee('Rainy');
employee.fullName = "Rain120";
console.log(employee.fullName)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

Playground (opens new window)

Note:

  • 存取器要求你将编译器设置为输出 ECMAScript 5或更高。 不支持降级到ECMAScript 3
  • 只带有 get不带有 set的存取器自动被推断为 readonly。 这在从代码生成 .d.ts文件时是有帮助的,因为利用这个属性的用户会看到不允许够改变它的值。

# 静态属性 & 方法

只能通过类来访问,实例不行

class Boy {
  static handsome: boolean = true;
  constructor(public name: string) {}
  static isHandsome() {
    return this.handsome;
  }
}

let rain120 = new Boy('Rain120');
console.log(Boy.handsome);
console.log(Boy.isHandsome);
console.log(rain120.handsome); // Property 'handsome' is a static member of type 'Boy'
console.log(rain120.isHandsome); // Property 'isHandsome' is a static member of type 'Boy'
1
2
3
4
5
6
7
8
9
10
11
12
13

Playground (opens new window)

# 继承

class Boy {
  handsome: boolean;
  name: string;
  
  constructor(name: string, handsome: boolean) {
    this.name = name;
    this.handsome = handsome;
  }
  
	isHandsome() {}
}

class Mine extends Boy {
  isHandsome() {
    return this.handsome;
  }
}

const mine = new Mine('Rain120', true);
console.log(mine)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

Playground (opens new window)

# 多态

export function trace(cities: any, prop?: string, enterBreakPoint?: boolean): void;

export function trace(cities: any, enterBreakPoint?: boolean): void;

export function trace(enterBreakPoint?: boolean): void;

export function trace(...args: any[]): void {
}
1
2
3
4
5
6
7
8

Playground (opens new window)

# 抽象类

abstract class Boy {
  handsome: boolean;
  name: string;
  
  constructor(name: string, handsome: boolean) {
    this.name = name;
    this.handsome = handsome;
  }
  
  abstract isHandsome(): boolean;
}

class Mine extends Boy {
  isHandsome() {
    return this.handsome;
  }
}

const mine = new Mine('Rain120', true);
console.log(mine);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

Playground (opens new window)

# 把类当接口使用

class Boy {
  handsome: boolean = true;
}

class Girl {
  beatiful: boolean = true;
}

enum Gender {
  'MALE',
  'FEMALE'
}

interface Person extends Boy, Girl {
  gender: Gender;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

Playground (opens new window)

# 快来耍耍啊

# 🌰🌰

// template
1

# 游乐场


# 参考答案

// answer
1

# 参考资料

handbook - classes (opens new window)

深入理解 TypeScript - 类 (opens new window)

ECMAScript 6入门 - Class基本语法 (opens new window)

类 (计算机科学) (opens new window)