大資料學習之路65-scala的泛型與隱式轉換
阿新 • • 發佈:2019-02-17
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
}
}
}
柯里化的方式: