zoukankan      html  css  js  c++  java
  • 泛型

     泛型:组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,用户就可以以自己的数据类型来使用组件。更加灵活

    泛型接口

      //泛型接口的第一种定义方式 当这个接口去限制函数,推荐使用这个
      interface IPrint {
        <T>(value: T): T
      }
      const print: IPrint = value => value
    
      print<string>('abc') //在函数调用时候显示传入T类型
      print('bbb') //这是简写 这样更普遍 利用了类型推断 编译器自动根据所传参数类型'abc'确定T的类型
    
      
      // 泛型接口的第二种定义方式  当这个接口去实现类implement 推荐使用这种定义方式。
      interface IIdentity1<T> {
        (arg: T): T
      }
      //这样 我就必须在函数定义的时候传入T类型,但是我不知道在函数定义时候传入什么类型。 而不是调用时候传入T类型,这种不好 
      const print1: IIdentity1<any> = value => value //这里IIdentity1必须要求我传入T的类型。传入具体的类型不太好。因为到时候限制我的调用,只能传入具体的类型,所以不得已传入any,传入any后面调用是没有提示的
      const r=print1(100) //r在这个时候是不明确它的类型的,编辑器是没有任何提示
      
      const print2: IIdentity1<string> = value => value 
      const r2=print2('abc') //r2明确知道是string类型。但是也只能传入string类型数据,失去了泛型的意义
      // print2(100)Error  Argument of type 'number' is not assignable to parameter of type 'string'.

    例子2

     // 定义泛型接口
      interface IAddFunc {
        <T>(value1: T, value2: T): string | number
      }
    
      const add: IAddFunc = (value1, value2) => {
        // 直接 return value1+value2 是会报错的 Operator '+' cannot be applied to types 'T' and 'T'.
        if (typeof value1 === 'string' && typeof value2 === 'string') return value1 + value2
        if (typeof value1 === 'number' && typeof value2 === 'number') return value1 + value2
      }
      console.log(add('aaa', 'bbb'))
      console.log(add(10, 20))

    更简洁的写法

    
    
    interface IAddFunc {
        <T>(value1: T, value2: T): T
      }
      const add: IAddFunc = <IAddFunc>(value1, value2) => { //<IAddFunc>是类型断言 尝试用as但是报错了why
        return value1 + value2
      }
      console.log(add(1, 2))
      console.log(add('a', 'b'))
      // add(1, 'a') //Error
     

    泛型类

    class ClassName<T> //T可以是基本数据类型:number|string; 也可以是自定义类类型。其他类型应该也可以传进来当作T的类型

    // 泛型类
      class MinClass<T>{
        list: Array<T> = []
        push(value: T): void {
          this.list.push(value)
        }
        getMin(): T {
          let minIndex = 0
          for (let i: number = 1; i < this.list.length; i++) {
            if (this.list[minIndex] > this.list[i]) minIndex = i //找出最小值索引
          }
          return this.list[minIndex]
        }
    
      }
      // 数字类型
      const minNumber = new MinClass<number>()
      minNumber.push(1)
      minNumber.push(30)
      minNumber.push(5)
      minNumber.push(-7)
      minNumber.push(0)
      minNumber.push(100)
      const minNum = minNumber.getMin() //minNum可以确定是number类型 无需显示表示,如果要表示就是number类型
    
    //字符串类型 const minString = new MinClass<string>() minString.push('f') minString.push('d') minString.push('4') minString.push('ebe') minString.push('few') minString.push('wewr') const minStr = minString.getMin() ///minStr可以确定是string类型 无需显示表示,如果要表示就是string
    class User {
        name: string;
        age: number;
        constructor(name: string, age: number) {
          this.name = name
          this.age = age
        }
      }
      class Article {
        title: string;
        time: Date
        desc?: string;
        constructor(title: string, desc?: string, time: Date = new Date) {
          this.title = title
          this.time = time
          this.desc = desc
        }
      }
    
    
    
      class SqlDb<T>{ //T可以是自定义类类型 我想甚至接口都可以传进来
        list: Array<T> = [] //定义一个空泛型对象
        add(item: T): void {
          this.list.push(item)
        }
      }
    
    
      const u1 = new User('zs', 10)
      const u2 = new User('lisi', 12)
      const article = new Article('三国演义', '曹操-孙权-刘备')
      const article1 = new Article('红楼梦', '贾宝玉-林黛玉-薛宝钗')
      const userDB = new SqlDb<User>() //看这里 传入自定义类型User
      
      userDB.add(u1)
      userDB.add(u2)
      const articleDB = new SqlDb<Article>() //看这里 传入自定义类型Article
      articleDB.add(article)
      articleDB.add(article1)

    泛型约束

    例子1

    interface ILength {
        length: number //限制泛型必须有length 属性
      }
      interface ILoggingIdentity {
        <T extends ILength>(value: T): T // <T extends ILength> 表示T类型必须有length属性
      }
      const loggingIdentity: ILoggingIdentity = value => {
        console.log(value.length);//我输出length属性 肯定是希望我传入的变量是有length属性的
        return value
      }
      loggingIdentity('abc')
      loggingIdentity({ name: 'zs', age: 10, length: 10 })

    泛型类型别名 type定义

     // 接口和type interface定义一个实实在在的接口,接口是一个真正的类型。type一般是定义别名,大白话:type 就是给一个类型起一个新名字。不会产生一个新的类型
      //类型别名type不能用extends implements扩展接口, interface可以
      // 泛型类型别名 type定义
      type CartType<T> = { list: Array<T> } | Array<T> //| 或者意思
      const cart1:CartType<string>={list:['1','2']}
      const cart2:CartType<number>=[1,2,3]

    综合案例

    里面有自定义类接口约束

    /*
      定义一个操作数据库的库同时支持mysql mssql mongDB(泛化),同时都有add update delete get方法(接口实现类)
    
      //注意描述:约束统一的规范(接口);代码的重用(泛型)
      */
      interface DBI<T> { //接口去定义方法 然后用类去实现这个接口implement
        add: (item: T) => boolean
        update: (item: T, id: number) => boolean
        deleteById: (id: number) => boolean
        getById: (id: number) => T
      }
      interface IId { //接口约束T必须有Id属性
        id: number
      }
      // 定义一个操作mysql数据库的类 注意:要实现泛型接口,这个类也应该是一个泛型类
      // 新的知识点 自定义类约束 <T extends IId> 约束T自定义类实例有id属性
      class MySqlDb<T extends IId> implements DBI<T>{
        list: Array<T> = []
        add(item: T) {
          this.list.push(item)
          return true
        }
        update(item: T, id: number) { return true }
        deleteById(id: number) {
          this.list = this.list.filter(item => item.id !== id)
    
          return true
        }
        getById(id: number): T {
          return this.list.find(item => item.id === id)
        }
    
      }
      class User {
        id: number
        user: string;
        password: string
        constructor(id: number, user: string, password: string) {
          this.user = user
          this.password = password
          this.id = id
        }
      }
      const u1 = new User(1000, 'zs', '123456')
      const u2 = new User(1001, 'lisi', '123456')
      const mySqlDb = new MySqlDb<User>()
      mySqlDb.add(u1)
      mySqlDb.add(u2)
      console.log('8888888888888888');
    
      console.log(mySqlDb.getById(1001))
      mySqlDb.deleteById(1001)
      console.log(mySqlDb.list);
    
    
      //定义一个操作mssql数据库的类
      class MsSqlDb<T> implements DBI<T>{
        add: (item: T) => boolean;
        update: (item: T, id: number) => boolean;
        deleteById: (id: number) => boolean;
        getById: (id: number) => T;
      }
      //定义一个操作mongDB数据库的类
      class MonDb<T> implements DBI<T>{
        add: (item: T) => boolean;
        update: (item: T, id: number) => boolean;
        deleteById: (id: number) => boolean;
        getById: (id: number) => T;
    
      }
  • 相关阅读:
    004 eclipse-jee-2021-06-R-win32-x86_64的使用
    男神鹏:Mac系统下查看和生成SSH Key
    每天一个Python小技巧(2)
    每天一个Python小技巧(1)之JSON转义
    测试平台系列(26) 编写用例详情页(1)
    测试平台系列(25) 编写用例树
    iOS 骨架屏
    OC 拖拽View
    OC 配置全局PCH 文件
    iOS masonary 约束 做动画
  • 原文地址:https://www.cnblogs.com/xiaoliziaaa/p/14930373.html
Copyright © 2011-2022 走看看