TypeScript 进阶指南(二):抽象类、接口实现与泛型类
3. 抽象类:定义契约的模板
用户疑问:“抽象类和普通类有什么区别?为什么要用它?”
核心概念:
抽象类 (abstract class
) 用于定义 需要被子类实现的属性和方法模板。它本身不能被实例化,但可以包含具体实现(非抽象成员),强制子类遵循特定结构。
示例与实战:
// 抽象类定义通用行为
abstract class Shape {
abstract area(): number; // 必须被子类实现
protected color: string = 'red'; // 非抽象属性
printColor() { // 非抽象方法
console.log(`Color: ${this.color}`);
}
}
class Circle extends Shape {
radius: number;
constructor(radius: number) {
super();
this.radius = radius;
}
// 必须实现抽象方法
area() {
return Math.PI * this.radius ** 2;
}
}
const circle = new Circle(5);
circle.printColor(); // 输出: Color: red
console.log(circle.area()); // 输出: 78.54...
使用场景:
- 需要定义公共逻辑(如
printColor
)但部分行为需子类定制(如area
)。 - 比接口更强大(可包含实现),适合有层次关系的类设计。
4. 类实现接口:多态性的另一种实现
用户疑问:“接口和抽象类都能约束类,如何选择?”
核心区别:
- 接口:仅定义类型契约,无实现,类可 实现多个接口。
- 抽象类:可包含实现,类只能 继承一个抽象类。
示例与实战:
// 定义多个接口
interface Loggable {
log(message: string): void;
}
interface Serializable {
serialize(): string;
}
// 类实现多个接口
class AppConfig implements Loggable, Serializable {
private object = {};
log(message: string) {
console.log(`[LOG] ${message}`);
}
serialize() {
return JSON.stringify(this.data);
}
}
const config = new AppConfig();
config.log("Config loaded"); // 调用接口方法
console.log(config.serialize()); // 输出: {}
设计技巧:
- 用接口定义 轻量级契约(如 API 响应结构)。
- 用抽象类定义 有共享逻辑的基类(如支付处理器基类)。
5. 泛型类:让类与类型共舞
用户疑问:“泛型在类中能解决什么问题?”
核心价值:
泛型类允许 延迟指定具体类型,使类能够处理多种数据类型而不丢失类型安全。
示例与实战:
// 泛型容器类
class Box<T> {
private content: T;
constructor(initialValue: T) {
this.content = initialValue;
}
getValue(): T {
return this.content;
}
setValue(newValue: T): void {
this.content = newValue;
}
}
// 使用不同类型初始化
const stringBox = new Box<string>("Hello");
console.log(stringBox.getValue().toUpperCase()); // 输出: HELLO
const numberBox = new Box<number>(42);
console.log(numberBox.getValue().toFixed(2)); // 输出: 42.00
进阶应用:
// 泛型约束(限制类型范围)
interface HasId {
id: number;
}
class Repository<T extends HasId> {
private items: T[] = [];
add(item: T) {
this.items.push(item);
}
findById(id: number): T | undefined {
return this.items.find(item => item.id === id);
}
}
// 使用约束后的泛型类
interface User extends HasId {
name: string;
}
const userRepo = new Repository<User>();
userRepo.add({ id: 1, name: "Alice" });
console.log(userRepo.findById(1)?.name); // 输出: Alice
总结:何时使用这些特性
特性 | 典型场景 |
---|---|
函数重载 | 参数类型影响返回值类型时(如解析器) |
接口继承 | 构建类型层次结构(如车辆->汽车->电动车) |
抽象类 | 定义包含部分实现的基类(如支付处理器基类) |
类实现接口 | 需要遵循多个独立契约时(如日志+序列化) |
泛型类 | 创建类型无关的容器或工具类(如集合类) |