概念:
泛型程序设计(generic programming)是程序设计语言的一种风格或范式。泛型允许程序员在强类型程序设计语言中编写代码时使用一些以后才指定的类型,在实例化时作为参数指明这些类型。
泛型应用:
场景:在做前后端交互数据接口统一返回格式定义的场景来进行泛型的实战训练。
- 通过ID查询指定数据返回的报文格式:

- 通过查询整个列表返回的报文格式:

通过分析两份返回报文可以得到一些信息:
- 公共且确定类属性
code
和message
;
- 公共但类型不确定的属性result,可能是对象也可能是数组;
- 返回列表数据的报文时list对象中需要包含公共的属性size和pages;
- 返回列表数据中的单个元素和返回指定数据的对象都包含一个公共的id字段,可以抽取到公共父类中使用,因为数据库必须有数据唯一的标识;
通过UML类图来看一下没有泛型的结构

BaseResponse:
抽取接口公共属性:code,message,result
| class BaseResponse { |
| code: number; |
| message: string; |
| result: any; |
| |
| constructor(code = 200, message: string, result: any) { |
| this.code = code; |
| this.message = message; |
| this.result = result; |
| } |
| } |
BaseData:
模拟数据库表数据的唯一主键id
| class BaseData { |
| id: number; |
| constructor(id: number) { |
| this.id = id; |
| } |
| } |
Person:
模拟数据库人员表单条数据
| class Person extends BaseData { |
| name: string; |
| age: number; |
| constructor(id: number, name: string, age: number) { |
| super(id); |
| this.name = name; |
| this.age = age; |
| } |
| } |
ListPersonData:
模拟数据库人员表多条数据
| class ListPersonData { |
| size: number; |
| pages: number; |
| persons: Person[]; |
| constructor(size: number, pages: number, persons: Person[]) { |
| this.size = size; |
| this.pages = pages; |
| this.persons = persons; |
| } |
| } |
ListPersonResponse:
| class ListPresonResponse extends BaseResponse { |
| |
| static toResponse(): object { |
| const person = new Person(100, "zhangsan", 18); |
| const result = new ListPersonData(20, 1, [person]); |
| const listDataResponse = new ListPresonResponse( |
| 200, |
| "数据加载完成", |
| result |
| ); |
| return listDataResponse; |
| } |
| } |
PersonResponse:
| class PersonResponse extends BaseResponse { |
| |
| static toResponse(): object { |
| const person = new Person(100, "zhangsan", 18); |
| const personResponse = new PersonResponse(200, "数据加载完成", person); |
| return personResponse; |
| } |
| } |
无泛型结构说明:
通过输出我们可以看到需求已经实现了,也可以看得出来类直接的关系比较紧密,不利于扩展和维护。我们看一看应用泛型后有什么变化吧。
对类进行升级-应用泛型:

1. 对BaseResponse升级支持泛型:
| class BaseResponse<T> { |
| code: number; |
| message: string; |
| result: T; |
| |
| constructor(code = 200, message: string, result: T) { |
| this.code = code; |
| this.message = message; |
| this.result = result; |
| } |
| } |
2. 对报错的ListPresonResponse配置泛型类型:
| class ListPresonResponse extends BaseResponse<ListPersonData> { |
| |
| static toResponse(): object { |
| const person = new Person(100, "zhangsan", 18); |
| const result = new ListPersonData(20, 1, [person]); |
| const listDataResponse = new ListPresonResponse( |
| 200, |
| "数据加载完成", |
| result |
| ); |
| return listDataResponse; |
| } |
| } |
- 配置泛型类型前的类型提示:(因为类型不确定只能是any)

- 配置泛型类型后的类型提示:

3. 对报错的PersonResponse配置泛型类型:
| class PersonResponse extends BaseResponse<Person> { |
| |
| static toResponse(): object { |
| const person = new Person(100, "zhangsan", 18); |
| const personResponse = new PersonResponse(200, "数据加载完成", person); |
| return personResponse; |
| } |
| } |
- 配置泛型类型前的类型类型提示:(因为类型不确定只能是any)

- 配置泛型类型后的类型类型提示:

4. 返回数据列表的ListPersonData类我们应用泛型后进行改造,抽取为统一的ListData类
切记ListData为公共类不显示的关联其他类,原来的persons属性改为list属性
| class ListData<T extends BaseData> { |
| size: number; |
| pages: number; |
| list: T[]; |
| constructor(size: number, pages: number, list: T[]) { |
| this.size = size; |
| this.pages = pages; |
| this.list = list; |
| } |
| } |
5. 调整ListPresonResponse符合我们的泛型规定
| class ListPresonResponse extends BaseResponse<ListData<Person>> { |
| |
| static toResponse(): object { |
| const person = new Person(100, "zhangsan", 18); |
| const result = new ListData(20, 1, [person]); |
| const listDataResponse = new ListPresonResponse( |
| 200, |
| "数据加载完成", |
| result |
| ); |
| return listDataResponse; |
| } |
| } |
应用泛型后说明:
应用泛型后的代码变得更容易扩展,我们如果新增一个商品表的话,对应的单条数据返回和多条数据返回的结构将可以很方便的在原来的基类上进行扩展了,如果需要在基类中进行属性的扩展和变更将受影响到所有子类中。
我们来看一下为商品对象报文增加的类:
| class Goods extends BaseData { |
| |
| } |
| class ListGoodsResponse extends BaseResponse<ListData<Goods>> { |
| |
| } |
| class GoodsResponse extends BaseResponse<Goods> { |
| |
| } |
结语:
泛型的应用使我们的程序在设计过程中对结构进行抽象但不指明具体类的类型,使的基类变得有规矩的宽松,延时到进行子类的实现时再补充泛型类型进行明确。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)