隱式轉換(Implicit Conversion)是Scala語言提供的一個強大的語法特性,是學習Scala必須要掌握的技能。
Scala的隱式轉換無處不在。在實際開發過程中,常常會自動地使用隱式轉換。
比如,在for循環中構造循環語句:
其實是方法調用,即1.to(5),但Int類型並沒有to方法,在執行時會自動進行隱式轉換,將Int類型轉換為scala.runtime.RichInt類型。
def to(end : scala.Int) : scala.collection.immutable.Range.Inclusive = { /* compiled code */ }
Int類型到RichInt類型的轉換定義在scal.LowPriorityImplicits 類中,可以通過如下的命令查看:
scala> :implicit -v
正是這些隱式轉換函數的存在,簡化了Scala程序代碼,使代碼更加簡潔。
在特定條件下,會自動調用Scala提供的隱式轉換函數來完成隱式轉換,但是Scala提供的隱式轉換函數畢竟是有限的。下面我們自己定義一個簡單的隱式轉換函數。
看一個示例:
package implicitconversion
import scala.collection.immutable.StringOps
object ImplicitTest {
def plus(a:Int, b:Int)={
a+b
}
def main(args: Array[String]): Unit = {
println(plus(1,2))
}
}
輸出結果為:3
但是,如果我們想讓字符串「1」和字符串「2」相加呢:
println(plus("1","2"))
就會出現如下錯誤:type mismatch-類型不匹配。
我們定義一個隱式函數做一個隱式轉換:
implicit def str2Int(x:String):Int = new StringOps(x).toInt
直接把String轉換為Int類型。
再次執行:println(plus("1","2"))
就工作正常了。編譯器發現傳入參數的類型與plus方法定義的類型不匹配,就會在當前作用域範圍內查找能夠將字符串String轉換成Int類型的隱式轉換函數。代碼中定義隱式轉換函數:str2Int(x:String):Int 正好滿足要求。
在IDEA 編輯器中,打開Implicit conversions提示【快捷鍵:Ctrl + Alt + Shift + 「+」】,如圖所示,可以看到自動調用了隱私轉換函數。
關閉Implicit conversions 提示的快捷鍵:Ctrl + Alt + Shift + 「-」
需要注意:如果在當前作用域範圍存在函數籤名相同,但函數名稱不同的兩個隱式轉換函數,則在進行隱式轉換時會報錯。
有興趣,可以再定義一個Double轉換成Int類的隱式轉換函數。
使用implicit關鍵字修改函數參數,這種形式的參數為隱式參數。
scala> def person(implicit name : String) = name //name為隱式參數
此時,直接調用person方法,編譯器說無法為參數name找到一個隱式值。
定義一個隱式值後再調用person方法:
scala> implicit val p="jack"
p: String = jack
scala> person
res5: String = jack
將變量p標記為 implicit,編譯器會在方法省略隱式參數的情況下,去搜索作用域內的隱式值作為參數傳入。
如果此時我們再定義一個隱式變量,調用方法時就會報錯:ambiguous implicit values。
隱式轉換必須滿足無歧義規則,在聲明隱式參數的類型是最好使用特別的或自定義的數據類型,不要使用Int、String這些常用類型,避免碰巧匹配。