类型参数

  • 表现形式:在名称后面以方括号表示, Array[T]

  • 何处使用

    • class 中,用于定义变量、入参、返回值

      class Pair[T, S](val first: T, val second: S)
      // scala 可自动推断具体的类型
      val p = new Pair(42, "String") // Pair[Int, String]
    • 函数、方法

      def getMiddle[T](a: Array[T]) = a(a.length / 2)
  • 类型边界

    • 上边界 T <: UpperBound

      // 比较大小
      class Pair[T](val first: T, val second: T) {
      def smaller = if (first.compareTo(second) < 0) first else second
      }

      无法确定 first 是否存在 compareTo 方法,所以必须添加约束,fist 必须是 Comparable 的子类型,即需要添加上边界

      class Pair[T <: Comparable[T]](val first: T, val second: T) {
      def smaller = if (first.compareTo(second) < 0) first else second
      }
    • 下边界 T >: LowerBound

      // 替换第一个元素
      class Pair[T](val first: T, val second: T) {
      def replaceFirst(newFirst: T) = new Pair[T](newFirst, second)
      }

      替换第一个元素为 T 的父类 R,那么返回类型是什么? 如果需要返回 R,则需要添加约束,即需要下边界;否则返回的类型为 Any

      // 返回类型自动推断为 new Pair[R]
      def replaceFirst[R >: T](newFirst: R) = new Pair(newFirst, second)
    • 上下文边界 T : ContextBound

      Scala 2.8 对 Array 进行了更新优化,使用隐式转换和 manifest 将数组整合为 Scala 的集合库

      def tabulate[T](len: Int, f: Int => T)(implicitm: ClassManifest[T]) = {
      val xs = new Array[T](len)
      for(i <- 0 until len) xs(i) = f(i)
      xs
      } // 简化后
      def tabulate[T: ClassManifest](len: Int, f: Int => T) = {
      val xs = new Array[T](len)
      for(i <- 0 until len) xs(i) = f(i)
      xs
      }
      • ClassTag, 指定运行时的类型,如 Array[Int] 在运行时想指定为 int[]

        import scala.reflect._
        def makePair[T : ClassTag](first: T, second: T) = {
        val r = new Array[T](2); r(0) = first; r(1) = second; r
        } makePair(4, 9) // 实际调用
        makePair(4, 9)(classTag) // new 操作,即 ClassTag[Int] 构建原始类型数组 int[2]
        classTag.newArray
    • 多个边界

      • 可同时添加上界和下界 T >: Lower <: Upper
      • 不可添加多个上界或多个下届,但可实现多个 trait,
        • T <: Comparable[T] with Serializable with Cloneable
      • 可指定多个上下文边界 T : Ordering : ClassTag
  • 类型约束

    • 测试是否相等 T =:= U
    • 测试是否为子类 T <:< U
    • 测试是否可转换 T => U

    要添加该约束,需添加隐式参数

    // 约束类
    class Pair[T](val first: T, val second: T)(implicit ev: T <:< Comparable[T]) // 约束方法调用,只有类型满足才能调用成功,否则报错
    class Pair[T](val first: T, val second: T) {
    def smaller(implicit ev: T <:< Ordered[T]) =
    if (first < second) first else second
    } // 便于类型推断
    def firstLast[A, C <: Iterable[A]](it: C) = (it.head, it.last)
    // 无法推断类型 A
    firstLast(List(1, 2, 3)) // [Nothing, List[Int]]
    // 添加约束关系
    def firstLast[A, C](it: C)(implicit ev: C <:< Iterable[A]) = (it.head, it.last)

最新文章

  1. Android 使用代码主动去调用控件的点击事件(模拟人手去触摸控件)
  2. react+redux完整项目
  3. js获取url
  4. markdown安装和使用
  5. uint8_t / uint16_t / uint32_t /uint64_t 是什么数据类型 - 大总结,看完全明白了
  6. 深入学习netty系列(1)
  7. 8.samba server与client配置
  8. 关于在android手机中腾讯、阿里产品不自定义虚拟键盘的想法
  9. 全面理解Unity加载和内存管理
  10. 【转】Qt 事件处理机制 (下篇)
  11. JavaEE学习路线
  12. Android Button四种点击事件和长按事件
  13. django第一天
  14. 个人 WPF+EF(DBFirst) 简单应用开发习惯及EF学习测试(备忘) -- 2
  15. Kafka技术内幕 读书笔记之(五) 协调者——延迟的加入组操作
  16. 通过C# WinForm控件创建的WPF WIndow窗口控件无法输入的问题
  17. SharePoint Framework 企业向导(五)
  18. (记忆化搜索 )The Triangle--hdu --1163
  19. JUnit4测试方法异常抛出实例
  20. 015-awk

热门文章

  1. windows docker 安装 Kitematic
  2. day 46
  3. Linux Firewalld 基础实例
  4. word2vector(含code)
  5. shell 的 正则表达式
  6. 五、Xpath与lxml类库
  7. https工具类
  8. 【EL表达式】EL从四大域中取数据
  9. Windows使用CMD命令查看进程和终止进程
  10. vector、ArryList、LinkedList的区别与联系