1. 程式人生 > >大資料學習之路65-scala的泛型與隱式轉換

大資料學習之路65-scala的泛型與隱式轉換

scala的泛型用[]

正常寫法:extends Comparable[Boy]

[T <: Comparable]    上界  upper bound

[T  >: Comparable]   下界   lower bound

[T : Comparable]    上下文界定  context bound

[T % Comparable]   檢視界定   view bound

[+T]     協變  

[-T]    逆變

1.假如我們有一個用泛型指定的比較方法,他是通過comoareTo方法比較的。可是Girl沒有compareTo方法怎麼辦?我們可以讓Girl實現Comparable介面,然後重寫compareTo方法即可,程式碼如下:

package com.test.test3

class Pair [T <: Comparable[T]]{
    def bigger(first:T,second:T): T ={
      if(first.compareTo(second)>0) first else second
    }
}
object Pair{
  def main(args: Array[String]): Unit = {
    val p = new Pair[Girl]
   val g =  p.bigger(new Girl("zhangsan",100,19),new Girl("lisi",99,16))
    println(g.name)
   
  }
}
package com.test.test3

class Girl (val name:String,val fv:Int,val age:Int) extends Comparable[Girl]{
  override def compareTo(o: Girl): Int = {
    if(this.fv == o.fv)
      this.age - o.age
    else
     o.fv - this.fv
  }
}

Pair使用的是上界

接下來我們看看檢視界定。

同樣是compareTo方法,但是假如我們傳進去的值是Int型別的如果還使用上界就會報錯,他報的錯是泛型的錯誤。而不是不能隱式轉換。因為Int方法沒有實現comparable介面根本就不能比較。所以這個時候就需要檢視界定來忽略泛型,強制隱式轉換,因為preDef中有Int到Integer的隱式轉換,而Integer有compareTo方法

package com.test.test3

class Pair [T <% Comparable[T]]{
    def bigger(first:T,second:T): T ={
      if(first.compareTo(second)>0) first else second
    }
}
object Pair{
  def main(args: Array[String]): Unit = {
   
    val p2 = new Pair[Int]
    val i =  p2.bigger(10,100)
    println(i)
  }
}

我們如果不使用上界和檢視界定的話能不能實現上面的要求呢?

其實我們還可以使用柯里化來實現:

package com.test.test3

class Pair2[T] {
     def bigger(first:T,second:T)(implicit f: T => Comparable[T]): T ={
       if(first.compareTo(second)>0) first else second
     }
}
object Pair2{
  def main(args: Array[String]): Unit = {
    val p = new Pair2[Int]
    val i = p.bigger(1,5)
    println(i)
  }
}

假如我們希望使用compareTo方法比較兩個boy可是我們並不想讓boy實現Comparable介面,這個時候我們可以自定義隱式轉換,並匯入這個隱式轉換。

Boy類:

package com.test.test4

class Boy(val name:String,val age:Int)

自定義的隱式轉換:

package com.test.test4

object MyPreDef {
    implicit val f= (b:Boy) => 
    {
            new Comparable[Boy]
          {
                override def compareTo(o: Boy): Int = {
                   b.age - o.age
                }
          }
    }
}

比較類:

package com.test.test4

class Pair[T <% Comparable[T]] {
    def choose(first:T,second:T): T ={
          if(first.compareTo(second)>0) first else second
    }
}
object Pair{
  def main(args: Array[String]): Unit = {
    import com.test.test4.MyPreDef._
      val p = new Pair[Boy]

      val b = p.choose(new Boy("zhangsan",19),new Boy("lisi",20))
    println(b.name)
  }
}

上下文界定需要一個隱式值(object)

package com.test.test5

class Pair[T:Ordering] {
    def select(first:T,second:T):T = {
             val o = implicitly[Ordering[T]]
             if(o.gt(first,second)) first else second
    }
}
object Pair{
  def main(args: Array[String]): Unit = {
    import MyPreDef._
    val p = new Pair[Boy]
    val boy: Boy = p.select(new Boy("zhangsan",19),new Boy("lisi",20))
    println(boy.name,boy.age)
  }

}
package com.test.test5

class Boy(val name:String, val age:Int)
package com.test.test5

object MyPreDef {
    implicit object girl2Ordering extends Ordering[Boy]{
      override def compare(x: Boy, y: Boy): Int = {
         x.age - y.age
      }
    }
}

柯里化的方式: