元素码农
基础
UML建模
数据结构
算法
设计模式
网络
TCP/IP协议
HTTPS安全机制
WebSocket实时通信
数据库
sqlite
postgresql
clickhouse
后端
rust
go
java
php
mysql
redis
mongodb
etcd
nats
zincsearch
前端
浏览器
javascript
typescript
vue3
react
游戏
unity
unreal
C++
C#
Lua
App
android
ios
flutter
react-native
安全
Web安全
测试
软件测试
自动化测试 - Playwright
人工智能
Python
langChain
langGraph
运维
linux
docker
工具
git
svn
🌞
🌙
目录
▶
TypeScript环境准备
安装与配置
第一个TS程序
编译流程解析
▶
基础类型系统
类型注解语法
原始类型定义
数组与元组
接口与对象
▶
高级类型系统
泛型编程
条件类型
映射类型
类型推断
类型保护
高级类型工具
▶
函数开发
函数类型声明
可选参数与默认值
箭头函数应用
函数重载
泛型函数
▶
类与面向对象
类的定义
继承与修饰符
存取器使用
抽象类与接口
泛型类与抽象类
访问修饰符与属性
▶
模块化开发
模块导入导出
类型声明文件
命名空间
模块解析策略
▶
工程实践
tsconfig详解
常见编译选项
项目构建配置
代码组织最佳实践
单元测试
调试技巧
▶
常见问题
类型错误处理
类型断言技巧
类型兼容性
版本迁移指南
发布时间:
2025-03-31 09:44
↑
☰
# 抽象类与接口 抽象类和接口是TypeScript中两个重要的面向对象概念,它们都用于定义类的契约。本文将详细介绍它们的使用方法和区别。 ## 抽象类 抽象类是一种不能被直接实例化的类,它可以包含抽象方法和具体方法: ```typescript abstract class Animal { // 抽象方法必须在派生类中实现 abstract makeSound(): void; // 具体方法可以直接使用 move(): void { console.log("Moving..."); } } class Dog extends Animal { makeSound(): void { console.log("Woof!"); } } // const animal = new Animal(); // 错误:不能创建抽象类的实例 const dog = new Dog(); dog.makeSound(); // 输出: "Woof!" dog.move(); // 输出: "Moving..." ``` ## 接口 接口定义了类应该具有的属性和方法: ```typescript interface Shape { area(): number; perimeter(): number; } class Circle implements Shape { constructor(private radius: number) {} area(): number { return Math.PI * this.radius ** 2; } perimeter(): number { return 2 * Math.PI * this.radius; } } class Rectangle implements Shape { constructor( private width: number, private height: number ) {} area(): number { return this.width * this.height; } perimeter(): number { return 2 * (this.width + this.height); } } ``` ## 抽象类vs接口 ### 主要区别 1. **实现数量** - 类只能继承一个抽象类 - 类可以实现多个接口 ```typescript interface Flyable { fly(): void; } interface Swimmable { swim(): void; } // 实现多个接口 class Duck implements Flyable, Swimmable { fly(): void { console.log("Flying..."); } swim(): void { console.log("Swimming..."); } } ``` 2. **构造函数** - 抽象类可以包含构造函数 - 接口不能包含构造函数 3. **方法实现** - 抽象类可以包含具体方法实现 - 接口只能包含方法签名 ## 实际应用场景 ### 1. 数据访问层 ```typescript interface Repository<T> { find(id: string): Promise<T>; findAll(): Promise<T[]>; create(item: T): Promise<T>; update(id: string, item: T): Promise<T>; delete(id: string): Promise<void>; } abstract class BaseRepository<T> implements Repository<T> { protected abstract collection: string; abstract find(id: string): Promise<T>; abstract findAll(): Promise<T[]>; // 共享实现 async create(item: T): Promise<T> { // 通用创建逻辑 return item; } async update(id: string, item: T): Promise<T> { // 通用更新逻辑 return item; } async delete(id: string): Promise<void> { // 通用删除逻辑 } } class UserRepository extends BaseRepository<User> { protected collection = "users"; async find(id: string): Promise<User> { // 具体实现 return null as any; } async findAll(): Promise<User[]> { // 具体实现 return []; } } ``` ### 2. 状态管理 ```typescript interface State { data: any; loading: boolean; error: Error | null; } interface Store { getState(): State; setState(newState: Partial<State>): void; subscribe(listener: () => void): () => void; } abstract class BaseStore implements Store { protected state: State = { data: null, loading: false, error: null }; private listeners: Set<() => void> = new Set(); getState(): State { return this.state; } setState(newState: Partial<State>): void { this.state = { ...this.state, ...newState }; this.notify(); } subscribe(listener: () => void): () => void { this.listeners.add(listener); return () => this.listeners.delete(listener); } protected notify(): void { this.listeners.forEach(listener => listener()); } abstract init(): void; abstract destroy(): void; } ``` ### 3. UI组件 ```typescript interface Component { render(): string; update(props: any): void; } abstract class BaseComponent implements Component { protected props: any; constructor(props: any) { this.props = props; } abstract render(): string; update(props: any): void { this.props = { ...this.props, ...props }; this.onUpdate(); } protected onUpdate(): void { // 可以被子类覆盖的钩子方法 } } class Button extends BaseComponent { render(): string { return `<button>${this.props.label}</button>`; } } ``` ## 最佳实践 1. **选择标准** - 使用接口定义公共API - 使用抽象类提供基础实现 ```typescript // 定义公共契约 interface Logger { log(message: string): void; error(message: string): void; } // 提供基础实现 abstract class BaseLogger implements Logger { abstract log(message: string): void; error(message: string): void { console.error(`[ERROR] ${message}`); } } ``` 2. **接口组合** ```typescript interface Readable { read(): string; } interface Writable { write(data: string): void; } interface Storage extends Readable, Writable { clear(): void; } ``` 3. **抽象类继承接口** ```typescript interface Disposable { dispose(): void; } abstract class Resource implements Disposable { protected isDisposed = false; abstract dispose(): void; protected checkDisposed(): void { if (this.isDisposed) { throw new Error("Resource is disposed"); } } } ``` ## 总结 抽象类和接口是TypeScript中两个强大的面向对象特性,它们各有优势: - **抽象类**适合于: - 需要共享代码实现 - 需要构造函数 - 需要访问修饰符 - **接口**适合于: - 定义纯粹的契约 - 需要多重实现 - 需要更灵活的类型组合 在实际开发中,我们应该根据具体需求选择合适的方式。通常的做法是: 1. 优先使用接口定义类型 2. 当需要共享实现时使用抽象类 3. 合理组合两者来创建灵活的类层次结构