Skip to main content

基本使用

TS 中的类和 ES6 中的类大部分相同

class Foo {
content: string = 'hello world';
say() {
return this.content;
}
}

class Bar extends Foo {
song() {
return 'dadada';
}
}

const msg = new Bar();
console.log(msg.say()); // hello world
console.log(msg.song()); // dadada

首先声明了一个 Foo 类,有 content 属性和 say 方法。然后声明了一个 Bar 类继承 Foo 类,创建实例后调用 say 和 song 方法均可行。

类的重写,就是子类可以重新编写父类里边的代码。比如在子类 Bar 中也写一个 say 方法,可以返回其他内容。 super关键字可以调用父类中的方法

class Bar extends Foo {
song() {
return 'dadada';
}
say() {
return super.say() + ' 666';
}
}

const msg = new Bar();
console.log(msg.say()); // hello world 666

类的访问类型

类的访问类型有publicprivateprotected三种,分别表示公共的、私有的、受保护的。

  • public类型在类的内部和外部都可访问,默认的类型就是public
  • private类型只能在类的内部访问,外部和继承的子类都不能访问
  • protected类型能在类的内部和继承的子类中访问,不能在外部访问
class Foo {
private count: number = 8;
protected content: string = 'hello world';
public say() {
return this.content;
}
}

class Bar extends Foo {
song() {
return this.content;
}
}

const msg = new Bar();
msg.say();

类的构造函数

在类 Foo 中定义一个未赋初值的 name 属性、一个赋初值的 age 属性,在创建实例时传递参数通过构造器给 name 属性赋值。

class Foo {
name: string;
age: number = 23;
constructor(name) {
this.name = name;
}
say() {
return this.age;
}
}
const res = new Foo('zgh');
console.log(res); // Foo { name: 'zgh', age: 23 }
console.log(res.say()); // 23

以上写法便于理解,但是还有简便写法:

class Foo {
constructor(public name: string, public age: number) {}
say() {
return this.name;
}
}
const res = new Foo('zgh', 23);
console.log(res); // Foo { name: 'zgh', age: 23 }

这种写法相当于定义了 name 和 age 属性,然后在构造器中进行赋值。

注意属性前面的public关键字不能少,否则报错Property 'name' does not exist on type 'Foo'.

在子类中使用构造器需要使用super()调用父类的构造器,如果有参数还需传递参数。

如果在父类中没有显示的声明构造器,也有默认的构造器constructor() {},仍需调用super()

class Foo {
constructor(public name: string, public age: number) {}
say() {
return this.name;
}
}

class Bar extends Foo {
constructor(public name: string, public age: number, public msg: string) {
super(name, age);
}
}

const res = new Bar('zgh', 23, 'handsome');
console.log(res); // Bar { name: 'zgh', age: 23, msg: 'handsome' }

注意:

  • 如果 constructor 被 private 修饰,则该类不允许被继承或者实例化
  • 如果 constructor 被 protected 修饰,则该类不允许被继承或者实例化
class Foo {
private constructor(public name: string, public age: number) {}
}

// 报错
class Bar extends Foo {
constructor(public name: string, public age: number) {
super(name, age);
}
}
// 报错
const res = new Foo('zgh', 23);

readonly

只读属性

如果 readonly 和其他访问修饰符同时存在的话,需要写在其后面

class Foo {
// readonly name: string;
constructor(public readonly name: string) {
this.name = name;
}
}
const foo = new Foo('zgh');
console.log(a.name);
// a.name = 'Tom'; // 报错

类的 getter、setter

假设有一个私有属性_age,外部是不能访问的,可以通过getter、setter属性从外部获取和设置

class girlFriend {
constructor(private _age: number) {}
get age() {
return this._age;
}
set age(age: number) {
this._age = age;
}
}
const girl = new girlFriend(18);
console.log(girl.age); // 18
girl.age = 20;
console.log(girl.age); // 20

抽象类

abstract 用于定义抽象类和其中的抽象方法。

  • 抽象类不允许被示例化
  • 抽象方法没有具体逻辑,不能加大括号
  • 抽象方法必须在子类中实现
// 抽象类
abstract class Hobby {
abstract skill(): string; // 抽象方法
}

class Song extends Hobby {
skill() {
return '唱';
}
}

class Jump extends Hobby {
skill() {
return '跳';
}
}

class Rap extends Hobby {
skill() {
return 'rap';
}
}