泛型
软件工程中,我们不仅要创建一致定义良好的API,同时也要考虑可重用性。组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。
在像c#和java这样的语言中,可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。这样用户就可以以自己的数据类型来使用组件。
通俗理解:泛型就是解决类、接口、方法的复用性、以及对不特定数据类型的支持。
// 下面的方法只能返回string类型
function getData(val: string): string {
return val;
}
// 需求:可以他那个是返回string和number类型,使用any可以解决这个问题,但是放弃了类型检查,我们需求是传入什么类型返回什么类型
// 下面的方法传入的参数类型和返回类型可以不一致
function getData(val: any): any {
return val;
}
泛型:可以支持你不特定的数据类型 ,要求:传入的参数和返回参数类型一致
-
泛型定义
使用大写字母T表示泛型,具体是什么类型是调用这个方法的时候决定的,定义泛型可以是任意大写字母,但是推荐使用T。
-
泛型函数
function getData<T>(val:T):T{ return val; } console.log(getData<number>(2134)); console.log(getData<string>('张万山')); console.log(getData<boolean>(true));
-
泛型类
比如有个最小堆算法,需要同时支持返回数字和字符串两种类型。通过泛型类实现
普通实现(下面的类只能传入number)
class MinClass { list: number[] = []; add(num: number) { this.list.push(num); } min(): number { let minNum = this.list[0]; for (let i = 0; i < this.list.length; i++) { if (minNum > this.list[i]) { minNum = this.list[i] } } return minNum; } } let m=new MinClass(); m.add(2435); m.add(234); m.add(2568); m.add(2342); m.add(256); m.add(68); m.add(25); console.log(m.min());
泛型类实现
class MinClass<T>{ list:T[]=[]; add(val:T){ this.list.push(val); } min(): T { let minNum = this.list[0]; for (let i = 0; i < this.list.length; i++) { if (minNum > this.list[i]) { minNum = this.list[i] } } return minNum; } } // 使用 let m=new MinClass<number>();// 实例化类,并且指定了类的T为number类型 m.add(2); m.add(24); m.add(3); m.add(25); console.log(m.min()); let m2=new MinClass<string>();// 实例化类,并且指定了类的T为string类型 m2.add('a'); m2.add('b'); m2.add('c'); m2.add('d'); console.log(m2.min());
-
泛型接口
普通函数接口
interface ConfigFn { (a: string, b: string): string; } let setData: ConfigFn = function (a: string, b: string): string { return a + '-' + b; } console.log(setData('张','三'));
泛型接口
-
第一种写法
interface ConfigFn{ <T>(val:T):T; } let setData:ConfigFn=function<T>(val:T):T{ return val; } console.log(setData(1234)); console.log(setData('张万山'));
-
第二种写法
interface ConfigFn<T>{ (val:T):T; } function getData<T>(val:T):T{ return val; } console.log(getData(123)); console.log(getData('abc'));
泛型使用示例:
泛型可以帮助我们避免重复的代码以及对不特定数据类型的支持(类型校验),下面我们看看把类当做参数的泛型类。
定义一个User的类,这个类的作用就是映射数据库字段,然后定义一个MySqlDb的类,这个类用于操作数据库,然后User类作为参数传入到MySqlDb中
class User { username: string | undefined; password: string | undefined; } class MySqlDb{ add(user:User):boolean{ // 增加数据 console.log(user); return true; } } let u=new User(); u.username='张三'; u.password='123456'; let db=new MySqlDb(); db.add(u); class ArticleCate { title: string | undefined; desc: string | undefined; status: number | undefined; } class MySqlDb{ add(info:ArticleCate):boolean{ // 增加数据 console.log(info); return true; } } let art=new ArticleCate(); art.title='三体'; art.desc='科幻小说'; art.status=2; let db=new MySqlDb(); db.add(art);
使用泛型类定义操作数据库的类
class MySqlDb<T>{ add(info: T): boolean { console.log(`新增成功`); console.log(info); return true; } update(info:T,id:number):boolean{ console.log(`修改成功`); console.log(info); console.log(id); return true; } }
给user表增加数据
定义一个user类,与数据库进行映射
class User { username: string | undefined; password: string | undefined; constructor(username: string | undefined, password: string | undefined) { this.username = username; this.password = password; } } let u = new User('张三', '123456'); let db = new MySqlDb<User>(); // db.add(u); db.update(u,1);
给ArticleCate增加数据
定义ArticleCate类
class ArticleCate { title: string | undefined; desc: string | undefined; status: number | undefined; constructor(params: { title: string | undefined, desc: string | undefined, status: number | undefined, }) { this.title = params.title; this.desc = params.desc; this.status = params.status; } } let art = new ArticleCate({ title: '三体', desc: '科幻小说', status: 2 }); let db1 = new MySqlDb<ArticleCate>(); // db1.add(art); db1.update(art,1);
-