Scala泛型编程说明和使用

Scala泛型编程说明和使用

泛型用于指定方法或类可以接受任意类型参数,参数在实际使用时才被确定,泛型可以有效 地增强程序的适用性,使用泛型可以使得类或方法具有更强的通用性。泛型的典型应用场景 是集合及集合中的方法参数。

泛型类和泛型方法

泛型类实例如下:

object GenreicTypeOps {
  def main(args: Array[String]): Unit = {
    val product=new ProductDao()
    val item=new Product(1234,"黄金",200)
    product.insert(item)

  }
  case class User(name:String, age:Int)
  case class Product(pid:Long, name:String, price:Int)
/*泛型类的特质*/
  trait BaseDao[T]{
    def insert(item:T)
  }
  class UserDao extends BaseDao[User]{
    override def insert(item:User): Unit = {
      println(s"向数据库中传入一个用户${item.name},年龄:${item.age}。")
    }
  }
  class ProductDao extends BaseDao[Product]{
    override def insert(item: Product): Unit = {
      println(s"向数据库中传入一个商品:${item.pid},价格:${item.price}。")
    }
  }
}

泛型方法实例如下(插入排序):

object GenericmethodOps {
  def main(args: Array[String]): Unit = {
    val array:Array[Int]=Array(5,18,1,8,19,-9,52,7,3,1)
    println("排序前:"+array.mkString("[",",","]"))
    insertSort[Int](array)
    println("排序后:"+array.mkString("[",",","]"))
  }
  def insertSort[T  <% Comparable[T]](array: Array[T]): Unit = {
    for(i <- 1 until array.size) {
        for(j <- 1 to i reverse) {
            if (array(j).compareTo(array(j-1)) > 0) {
                swap(array,j-1,j)
              }
          }
      }
  }
  def swap[T](array: Array[T],i:Int,j:Int): Unit = {
    val tmp=array(i)
    array(i)=array(j)
    array(j)=tmp
  }
}

泛型上界和下界限定

类型变量上界和下界限定是指在泛型的基础上,对泛型的范围进行进一步的界定,从而缩小泛型的具体范围。比如,要求某个 泛型类型,必须是某个类的子类,这样在程序中就可以放心的调用父类的方法,程序才能正 常的使用与运行。Scala 的上下边界特性允许泛型类型是某个类的子类,或者是某个类的父类。具体语法如下:

  1. U >: T 这是类型下界的定义,也就是 U 必须是类型 T 的父类(或本身,自己也可以认为是自己的父 类)。
  2. S <: T 这是类型上界的定义,也就是 S 必须是类型 T 的子类(或本身,自己也可以认为是自己的子 类)。

上界:

class GenericTypeTest2 { 
  def compare[T <: Comparable[T]](first:T,second:T)={ 
    if (first.compareTo(second)>0) 
      first 
    else 
      second 
  } }

**T <: Comparable[T] **表示泛型 T 的类型的最顶层类是 Comparable,所有输入是 Comparable 的子类都是合法的,其 它的都是非法的,因为被称为上界 。

下界:

class A 
class B extends A 
class C extends B 
class D extends C 
opt[T >: C]

opt[T >: C]表示 T 的类型只能是 A,B,C 了,不能是 D(其实就是限制了最底层的类型是什么)。在类 的继承结构体系中,从上到下,只能到类型 C 为止 。

Scala 视图界定

上面讲的类型变量界定建立在类继承层次结构的基础上,但有时候这种限定不能满足实际要 求,如果希望跨越类继承层次结构时,可以使用视图界定来实现的,其后面的原理是通过隐 式转换来实现。 隐含参数和方法也可以定义隐式转换,称作视图。视图的绑定从另一个角度看就是 implicit 的转换。主要用在两个场合: 1、当一个 T 类型的变量 t 要装换成 A 类型时;2、当一个类型 T 的变量 t 无法拥有 A 类型的 a 方法或变量时 其实视图的绑定是为了更方便的使用隐式装换 视图界定利用<%符号来实现 (上述插入排序就是这么处理的)。
利用<%符号对泛型 S 进行限定,它的意思是 S 可以是 Comparable 类继承层次结构中实现了 Comparable 接口的类,也可以是能够经过隐式转换得到的实现了 Comparable 接口的类。 上述代码的语句在视图界定中是合法的,因为 Int 类型此时会隐式转换为 RichInt 类,而 RichInt 类属于 Comparable 继承层次结构。Int 类会隐式转换成 RichInt 类,RichInt 并不是直 接实现 Comparable 口,而是通过 ScalaNumberProxy 类将 Comparable 中的方法继承过来。

协变和逆变

协变定义形式如:

trait List[+T]{}

当类型 B 是类型 A 的子类型时,则 List[B]也可以认为是 List[A}的子类型,即 List[B]可以泛化 为 List[A]。

逆变定义形式如:

trait List[-T]{} 

当类型 B 是类型 A 的子类型,则 List[A]反过来可以认为是 List[B]的子类型。也就是被 参数化类型的泛化方向与参数类型的方向是相反的,所以称为逆变(contravariance) 。

你可能感兴趣的:(Scala,spark,scala)