1. 程式人生 > >scala 隱式詳解(implicit關鍵字)

scala 隱式詳解(implicit關鍵字)

掌握implicit的用法是閱讀spark原始碼的基礎,也是學習scala其它的開源框架的關鍵,implicit 可分為:

  • 隱式引數
  • 隱式轉換型別
  • 隱式呼叫函式

1.隱式引數

當我們在定義方法時,可以把最後一個引數列表標記為implicit,表示該組引數是隱式引數。一個方法只會有一個隱式引數列表,置於方法的最後一個引數列表。如果方法有多個隱式引數,只需一個implicit修飾即可。 當呼叫包含隱式引數的方法是,如果當前上下文中有合適的隱式值,則編譯器會自動為改組引數填充合適的值。如果沒有編譯器會丟擲異常。當然,標記為隱式引數的我們也可以手動為該引數新增預設值。def foo(n: Int)(implicit t1: String, t2: Double = 3.14)

scala > def calcTax(amount: Float)(implicit rate: Float): Float = amount * rate
scala > implicit val currentTaxRate = 0.08F
scala > val tax = calcTax(50000F) // 4000.0

如果編譯器在上下文沒有找到第二行程式碼會報錯

2.隱式地轉換型別

使用隱含轉換將變數轉換成預期的型別是編譯器最先使用 implicit 的地方。這個規則非常簡單,當編譯器看到型別X而卻需要型別Y,它就在當前作用域查詢是否定義了從型別X到型別Y的隱式定義
例子:

scala> val i: Int = 3.5 //直接報錯
加上這句:
scala> implicit def double2Int(d: Double) = d.toInt
再執行,沒報錯
scala> val i: Int = 3.5  //i=3

3.隱式呼叫函式

隱式呼叫函式可以轉換呼叫方法的物件,比如但編譯器看到X .method,而型別 X 沒有定義 method(包括基類)方法,那麼編譯器就查詢作用域內定義的從 X 到其它物件的型別轉換,比如 Y,而型別Y定義了 method 方法,編譯器就首先使用隱含型別轉換把 X 轉換成 Y,然後呼叫 Y 的 method。
例子:

class SwingType{
  def  wantLearned(sw : String) = println("兔子已經學會了"+sw)
}
object swimming{
  implicit def learningType(s : AminalType) = new SwingType
}
class AminalType
object AminalType extends  App{
  import com.mobin.scala.Scalaimplicit.swimming._
  val rabbit = new AminalType
    rabbit.wantLearned("breaststroke")         //蛙泳
}

上例中編譯器在rabbit物件呼叫時發現物件上並沒有wantLearning方法,此時編譯器就會在作用域範圍內查詢能使其編譯通過的隱式檢視,找到learningType方法後,編譯器通過隱式轉換將物件轉換成具有這個方法的物件,之後呼叫wantLearning方法