“不畏惧,不将就,未来的日子好好努力”——大家好!我是小芝麻😄
类(Class)定义了一件事物的抽象特点,包含它的属性和方法
1、定义类
在 TypeScript
中,我们也是通过 Class
关键字来定义一个类, 使用 constructor
定义构造函数。
构造函数: constructor
- 主要用于初始化类的成员变量属性
- 类的对象创建时自动调用执行
- 没有返回值
1class Animal {
2 public name: string;
3 constructor(name: string) {
4 this.name = name;
5 }
6 sayHi(): string {
7 return `My name is ${this.name}`;
8 }
9}
2、类的继承
使用 extends
关键字实现继承,子类中使用 super
关键字来调用父类的构造函数和方法。
- 子类继承父类后子类的实例就拥有了父类中的属性和方法,可以增强代码的可复用性
- 将子类共用的方法抽象出来放在父类中,自己特殊逻辑放在子类中重写父类的逻辑
- super 可以调用父类上的方法和属性: (相当于ES5的:在静态方法和构造函数中指向父类; 在普通函数中指向父类的prototype;)
1class Animal {
2 public name: string;
3 constructor(name: string) {
4 this.name = name;
5 }
6 sayHi(): string {
7 return `My name is ${this.name}`;
8 }
9}
10
11class Cat extends Animal {
12 constructor(name) {
13 super(name);
14 console.log(this.name);
15 }
16 sayHi(): string {
17 return 'Meow, ' + super.sayHi();
18 }
19}
20
21let c = new Cat('Tom');
22console.log(c.sayHi());
2.1 重写(override) VS 重载(overload)
- 重写是指子类重写继承自父类的方法
- 重载是指为同一个函数提供多个类型定义
2.2 继承 VS 多态
- 继承(inheritance)子类继承父类,子类除了拥有父类的所有特性外,还有一些具体的特性
- 多态(Polymorphism)由继承而产生了相关的不同的类,对同一个方法可以有不同的行为
3、类的修饰符
TypeScript
中有三类访问修饰符,分别是: public
、private
、protected
。不写默认为 public
- public :自己、自己的子类 和其他类都可以访问 (默认值)
- protected 受保护的 自己和自己的子类能访问, 其他类不能访问
- private 私有的 只能自己访问,自己的子类不能访问,其他类更不能访问
1class Father {
2 public name: string
3 protected age: number
4 private money: number
5
6 constructor(name: string, age: number, money: number) {
7 this.name = name
8 this.age = age
9 this.money = money
10 }
11 getName(): string {
12 return this.name
13 }
14 setName(name: string): void {
15 this.name = name
16 }
17}
18class child extends Father {
19 constructor(name: string, age: number, money: number) {
20 super(name, age, money)
21 }
22 desc() {
23 console.log(`${this.name}${this.age}${this.money}`)
24
25 }
26}
27let children = new child('金色小芝麻', 18, 1000)
28console.log(children.name)
29console.log(children.age)
30console.log(children.money)
- 当构造函数修饰为
private
时,该类不允许被继承或者实例化:
1class Animal {
2 public name: string;
3 private constructor(name: string) {
4 this.name = name;
5 }
6}
7class Cat extends Animal {
8 constructor(name: string) {
9 super(name);
10 }
11}
12
13let a = new Animal('Jack');
- 当构造函数修饰为
protected
时,该类只允许被继承:
1class Animal {
2 public name: string;
3 protected constructor(name: string) {
4 this.name = name;
5 }
6}
7class Cat extends Animal {
8 constructor(name: string) {
9 super(name);
10 }
11}
12
13let a = new Animal('Jack');
4、readonly
readonly 修饰的变量只能在属性声明时或 构造函数
中初始化
1class Animal {
2
3 public readonly name: string
4 constructor(name: string) {
5 this.name = name
6 }
7 changeName(name: string) {
8 this.name = name
9 }
10}
11let a = new Animal('hello')
12a.name = '111'
13a.changeName('nihao')
14console.log(a)
readonly 只是在 编译
阶段进行代码检查。运行时依然能打印
5、参数属性
在上面的例子中,都是在类的定义的顶部初始化实例属性,在 constructor
里接收参数然后对实例属性进行赋值,参数属性就是为了简化这一过程的
直接在
constructor
构造函数的参数前面加上修饰符或readonly
=> 等同于在类中定义该属性同时给该属性赋值,使代码更简洁。
1class User {
2 constructor(public name: string) {}
3}
4let user = new User('hello')
5console.log(user.name)
6user.name = 'nihao'
7console.log(user.name)
6、存取器
- 在
TypeScript
中,我们可以通过getter
/setter
来改变一个类中属性的读取和赋值行为
1class Person {
2 name: string
3 constructor(name: string) {
4 this.name = name
5 }
6 get getName() {
7 return this.name
8 }
9 set setName(val: string) {
10 this.name = val.toUpperCase()
11 }
12}
13let p1 = new Person('nihao')
14console.log(p1.getName)
15p1.setName = 'hello'
16console.log(p1.name)
7、静态属性和静态方法static
使用 static
修饰符修饰的方法称为静态方法,它们不需要实例化,而是直接通过类来调用:
1class Father {
2 public name: string
3 constructor(name: string) {
4 this.name = name
5 }
6 public static className: string = 'Father'
7 static getClassName(): string {
8 return Father.className
9 }
10
11}
12console.log(Father.className)
13console.log(Father.getClassName())
8、抽象类和抽象方法abstract
使用
abstract
关键字来定义抽象类和在抽象类内部定义抽象方法。
8.1 抽象类
- 抽象描述一种抽象的概念,做为其它类的基类使用
- 无法创建抽象类的实例,抽象类只能被继承
1abstract class Animal {
2 name!: string
3 abstract speak(): void
4}
5
6class Cat extends Animal {
7 speak() {
8 console.log('喵喵喵')
9 }
10}
11
12let animal = new Animal();
13let cat = new Cat()
14cat.speak()
8.2 抽象方法
- 抽象方法不能在抽象类中实现,只能在抽象类的具体子类中实现,而且必须实现
- 抽象方法只能出现在抽象类中
1abstract class Animal {
2 name: string
3 abstract speak(): void = ()=>{}
4}
5class Cat extends Animal {
6 speak() {
7 console.log('喵喵喵')
8 }
9}
- 子类可以对抽象类进行不同的实现
1abstract class Animal {
2 abstract speak(): void
3}
4class Dog extends Animal {
5 speak() {
6 console.log('汪汪汪')
7 }
8}
9
10class Cat extends Animal {
11 speak() {
12 console.log('喵喵喵')
13 }
14}
8.3 抽象类 VS 接口
- 不同类之间公有的属性或方法,可以抽象成一个接口(interfaces), 而抽象类是供其他类继承的基类
- 抽象类本质是一个无法被实例化的类,可以包含成员的实现细节,而接口仅能够用于描述,既不能提供方法的实现细节,也不为属性进行初始化
- 一个类可以继承一个类或抽象类,但可以实现(implements)多个接口
- 抽象类也可以实现接口
1abstract class Animal {
2 name: string;
3 constructor(name: string) {
4 this.name = name;
5 }
6 abstract speak(): void;
7}
8interface Flying {
9 fly(): void
10}
11interface age {
12 age: number
13}
14class Dog extends Animal implements Flying, age {
15 age: 18
16 speak() {
17 console.log('汪汪汪')
18 }
19 fly() {
20 console.log('我会飞')
21 }
22}
| 访问控制修饰符 | private、protected、public | | 只读属性 | readonly | | 静态属性 | static | | 抽象类、抽象方法 | abstract |
参考文献
[1]. TypeScript中文网
[2]. TypeScript 入门教程
个人笔记记录 2021 ~ 2025