这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战
为了有效消化知识点,我决定放慢一点速度,今天就学一个:类类型。不贪吃,仔细消化嘿嘿。
下面这个是脑图版的学习笔记
,关键信息快速 Get 😉 复习也方便,我真棒。
好了,不臭屁了,下面结合具体例子看看今天的知识点 ——
类
ES6 中正式引入了"类"的概念,使我们能够使用基于类的面向对象方式。下面我们先简单回顾一下类的基础用法。
类是啥
类是由 class 关键字定义,可以包含多个属性和方法,类似对象的数据结构。
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
}
let greeter = new Greeter("world");
类的继承
通过 extends 关键字,我们可以快速得到一个继承了基类属性和方法的子类,也可以称之为派生类,而基类也称为超类。
//基类
class Animal {
move(distanceInMeters: number = 0) {
console.log(`Animal moved ${distanceInMeters}m.`);
}
}
//派生类
class Dog extends Animal {
bark() {
console.log('Woof! Woof!');
}
}
//Dog实例,拥有 Animal 和 Dog 的属性和方法
const dog = new Dog();
dog.bark();
dog.move(10);
dog.bark();
类的静态属性和方法
static 关键字用于定义类的静态属性和静态方法,静态属性、静态方法直接存在于类,直接通过类访问,且不会被实例继承。
class Foo {
static classMethod() {
return 'hello';
}
}
//直接通过类访问
Foo.classMethod() // 'hello'
//无法通过实例访问
var foo = new Foo();
foo.classMethod()
// TypeError: foo.classMethod is not a function
TypeScript 中的类
TypeScript 对类的增强有几个方面:访问修饰符、存取器、抽象类,下面逐个看看。
修饰符
- public:在任何地方可见、公有的属性或方法(缺省情况下,默认都是 public)
- private:仅在同一类中可见、私有的属性或方法(只可以在类的内部可见,实例无法访问)
- protected:仅在类自身及其子类中可见、受保护的属性或方法
- readonly:可见,但不可修改
class Son {
public firstName: string;
private lastName: string = 'Stark';
constructor(firstName: string) {
this.firstName = firstName;
this.lastName; // ok
}
}
const son = new Son('Tony');
console.log(son.firstName); // => "Tony"
son.firstName = 'Jack';
console.log(son.firstName); // => "Jack"
console.log(son.lastName); // ts(2341) Property 'lastName' is private and only accessible within class 'Son'.
存取器
TS 中,可以通过getter、setter截取对类成员的读写访问(同 ES6中的 proxy ?)
抽象类
由 abstract 关键字定义,一种不能被实例化、仅能被子类继承的特殊类。
除了普通的属性和方法,抽象类还可以定义需要由派生类实现的属性和方法,即抽象属性、抽象方法。抽象属性、抽象方法同样由 abstract 关键字定义。
abstract class Department {
constructor(public name: string) {
}
printName(): void {
console.log('Department name: ' + this.name);
}
abstract printMeeting(): void; // 必须在派生类中实现
}
class AccountingDepartment extends Department {
constructor() {
super('Accounting and Auditing'); // 在派生类的构造函数中必须调用 super()
}
printMeeting(): void {
console.log('The Accounting Department meets each Monday at 10am.');
}
generateReports(): void {
console.log('Generating accounting reports...');
}
}
let department: Department; // 允许创建一个对抽象类型的引用
department = new Department(); // 错误: 不能创建一个抽象类的实例
department = new AccountingDepartment(); // 允许对一个抽象子类进行实例化和赋值
department.printName();
department.printMeeting();
department.generateReports(); // 错误: 方法在声明的抽象类中不存在
由于不能被实例化,抽象类通常用于对基础逻辑的封装和抽象。
类类型
在声明类的时候,其实也同时声明了一个特殊的类型,这个类型的名字就是类名,表示类实例的类型。
class A {
name: string;
constructor(name: string) {
this.name = name;
}
}
const a1: A = {}; // ts(2741) Property 'name' is missing in type '{}' but required in type 'A'.
const a2: A = { name: 'a2' }; // ok
上述例子等同于
class A {
name: string;
constructor(name: string) {
this.name = name;
}
}
interface AInstanceType {
name: string;
}
const a: AInstanceType = { name: 'a' }
关于类类型和接口的详细说明,参考之前写的 《TypeScript 中的 implements 和 extends》