• Scala Type Parameters 1


    类型参数

    • 表现形式:在名称后面以方括号表示, 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)
      
  • 相关阅读:
    Flink集群模式部署及案例执行
    Solr查询解析及内核剖析
    Spark Streaming流计算核心概念
    Kaldi语音识别CVTE模型实战
    Kaldi基础代码库及建模
    Kaldi样例实战
    Solr文本分析剖析【文本分析、分词器详解、自定义文本分析字段及分词器】
    Flink场景分析与比较【事件驱动、数据分析、数据管道】
    什么是Apache Flink实时流计算框架?
    基于Tesseract实现图片文字识别
  • 原文地址:https://www.cnblogs.com/yuanzam/p/11638643.html
Copyright © 2020-2023  润新知