TypeScript中的类修饰符和抽象类
Howard 8/22/2021 Typescript
在 TypeScript 中,类的属性和方法可以使用不同的修饰符来限制它们的可见性和行为。本文将介绍 TypeScript 中常用的类修饰符和抽象类的概念以及它们的用法。
# 类的修饰符
在 TypeScript 中,类的属性和方法可以使用以下修饰符进行修饰:
# public
public 是默认的修饰符,表示属性和方法可以在类的内部、继承类和类的实例中自由访问。这是最宽松的修饰符。
class Animal {
public name: string;
constructor(theName: string) {
this.name = theName;
}
public move(distanceInMeters: number) {
console.log(`${this.name} moved ${distanceInMeters}m.`);
}
}
// 等价于
class Animal {
name: string;
constructor(theName: string) { this.name = theName; }
move(distanceInMeters: number) {
console.log(`${this.name} moved ${distanceInMeters}m.`);
}
}
# protected
protected 修饰符稍微严格一些,只有类的内部和继承类中可以访问,类的实例不能访问。
class Person {
protected name: string;
constructor(name: string) {
this.name = name;
}
}
class Employee extends Person {
constructor(name: string) {
super(name);
}
public getElevatorPitch() {
return `Hello, my name is ${this.name}.}`;
}
}
let howard = new Employee("Howard");
console.log(howard.getElevatorPitch());
console.log(howard.name); // 错误
# private
private 是最严格的修饰符,只有类的内部可以访问,继承类和类的实例都不能访问。
class Person {
private name: string;
constructor(name: string) {
this.name = name;
}
}
class Employee extends Person {
constructor(name: string) {
super(name);
}
public getElevatorPitch() {
return `Hello, my name is ${this.name}.}`; // 错误
}
}
let howard = new Person("Howard");
console.log(howard.name); // 错误
# readonly
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 是只读的。
class Octopus {
readonly numberOfLegs: number = 8;
constructor(readonly name: string) {
}
}
# static
static 修饰符表示属性和方法属于类本身,而不是类的实例。它可以通过类名来访问,而不需要创建类的实例。
class Grid {
static origin = {x: 0, y: 0};
calculateDistanceFromOrigin(point: {x: number; y: number;}) {
let xDist = (point.x - Grid.origin.x);
let yDist = (point.y - Grid.origin.y);
return Math.sqrt(xDist * xDist + yDist * yDist);
}
constructor (public scale: number) { }
}
let grid1 = new Grid(1.0); // 1x scale
let grid2 = new Grid(5.0); // 5x scale
console.log(grid1.calculateDistanceFromOrigin({x: 10, y: 10}));
console.log(grid2.calculateDistanceFromOrigin({x: 10, y: 10}));
console.log(Grid.origin); // 可以直接访问静态属性
# 抽象类(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(); // 错误: 方法在声明的抽象类中不存在
抽象类在设计模式中常用于定义接口和基类,它提供了一种定义标准和约束子类的方式。
通过类的修饰符和抽象类的概念,TypeScript 提供了更加丰富的面向对象编程工具,可以帮助您更好地组织和管理代码。