类
在 TypeScript 中,类(Class)是面向对象编程的基本构建块,用于创建具有属性(Fields)和方法(Methods)的对象。TypeScript 类是对 JavaScript 类的超集,提供了静态类型检查、访问修饰符、抽象类、继承、接口实现等特性。以下是一些关于如何在 TypeScript 中定义和使用类的关键概念
基本类定义
ts
class Person {
name: string; // 成员属性(字段)
constructor(name: string) {
// 构造函数
this.name = name;
}
greet(): void {
// 成员方法
console.log(`Hello, my name is ${this.name}`);
}
}
const person = new Person("Alice");
person.greet(); // 输出: Hello, my name is Alice访问修饰符
- public(默认):成员可以在任何地方被访问。
- private:成员只能在类的内部被访问。
- protected:成员可以在类的内部及继承类中被访问。
ts
class Animal {
protected species: string; // 受保护的属性
constructor(species: string) {
this.species = species;
}
}
class Dog extends Animal {
constructor() {
super("Canine");
}
displaySpecies() {
console.log(`I am a ${this.species}`);
}
}
const dog = new Dog();
dog.displaySpecies(); // 输出: I am a Canine静态成员
静态成员属于类本身,而不属于类的实例。
ts
class Counter {
static count = 0; // 静态属性
static increment() {
// 静态方法
Counter.count++;
}
}
Counter.increment();
console.log(Counter.count); // 输出: 1继承
TypeScript 支持基于类的继承,子类可以继承父类的属性和方法。
ts
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
move(distanceInMeters: number = 0) {
console.log(`${this.name} moved ${distanceInMeters}m.`);
}
}
class Snake extends Animal {
constructor(name: string) {
super(name);
}
move(distanceInMeters = 5) {
console.log("Slithering...");
super.move(distanceInMeters);
}
}
const sam = new Snake("Sammy the Python");
sam.move(); // 输出: Slithering... Sammy the Python moved 5m.接口实现
类可以实现接口,确保类遵循特定的结构约定。
ts
interface Resizable {
resize(width: number, height: number): void;
}
class Square implements Resizable {
constructor(private width: number) {}
resize(newWidth: number, newHeight: number): void {
this.width = newWidth; // 假设正方形,宽度和高度相同
}
}
const square = new Square(10);
square.resize(20, 20); // 虽然传入了高度,但这里简化处理抽象类
抽象类不能被实例化,用于定义子类必须实现的方法。
ts
abstract class Shape {
abstract calculateArea(): number;
// 部分实现的方法,提供通用逻辑
logShapeInfo(): void {
console.log(`This is a ${this.name}.`);
}
}
class Circle extends Shape {
constructor(private radius: number) {
super();
}
calculateArea(): number {
return Math.PI * this.radius ** 2;
}
// 调用父类的logShapeInfo方法,并添加自己的逻辑
logShapeInfo(): void {
super.logShapeInfo();
console.log(`The area of this Circle is ${this.calculateArea()}.`);
}
}
const circle = new Circle(5);
console.log(circle.calculateArea()); // 输出圆的面积通过这些基本概念和高级特性,TypeScript 类为构建复杂、可维护的应用程序提供了强大的支持。
接口类和抽象类区别
在 TypeScript 中,接口(Interfaces)和抽象类(Abstract Classes)都是实现抽象化和多态性的重要工具,但它们在使用场景上各有侧重:
接口(Interfaces)
- 定义类型规范:接口用于定义一个结构的形状,即对象需要具备的属性和方法。它适合于描述一个组件或服务期望的数据结构,不涉及具体实现,适用于多种实现方式的场景。
- 实现多重继承:TypeScript 不支持类的多重继承,但一个类可以实现多个接口,这样可以组合多个接口的规范,实现多重继承的效果。
- 解耦代码:接口作为契约,可以降低模块间的耦合度,使得各部分代码可以独立开发和测试,同时保证类型安全。
- 类型断言和类型守卫:接口可以作为类型断言的基础,帮助开发者在运行时确认变量的类型,同时也便于在类型系统中进行类型检查。
抽象类(Abstract Classes)
- 共享实现:抽象类可以包含具体实现的方法和抽象方法(没有具体实现的方法),这样子类可以从抽象类继承并复用这些实现,同时必须实现抽象方法。
- 强制实现:通过定义抽象方法,抽象类可以强制子类实现某些方法,保证子类遵循一定的规范或行为模式。
- 模板方法模式:抽象类可以定义一个操作中的算法骨架,而将某些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
- 状态或行为的标准化:在需要定义一系列具有相同基础行为但又需要具体实现差异的类时,抽象类可以作为一个标准模板,提供共通的实现和接口。
应用场景对比
- 更倾向于定义“做什么”,强调的是类型和结构的规范,适用于定义 API 接口、数据模型、以及定义不同组件间交互的契约。
- 则倾向于定义“怎么做”,它不仅提供接口规范,还可能包含部分实现,适用于提供基础实现、定义框架或库中的基类,以及需要实现共享行为的场景。