作用
簡單說,隱式轉換就是:當Scala編譯器進行類型匹配時,如果找不到合適的候選,那么隱式轉化提供了另外一種途徑來告訴編譯器如何將當前的類型轉換成預期類型。
話不多說,直接測試
ImplicitHelper.scala
package com.donews.localspark /** * Created by reynold on 2017/3/20. */ object ImplVal { implicit val name: String = "reynold" } /** * 定義成trait的話,可以讓ScalaDemo繼承,這樣就可以自動引入了 */ trait ImplVal { implicit val name: String = "reynold" } object ImplicitHelper { /** * 隱式參數 * 隱式參數一般和柯里化進行結合,使用該函數不用給出implicit的值 * * @param param * @param impl */ def echo(param: String)(implicit impl: String) { println(param + "," + impl) } /** * 隱式轉換函數是指在同一個作用域下面,一個給定輸入類型並自動轉換為指定返回類型的函數, * 這個函數和函數名字無關,和入參名字無關,只和入參類型以及返回類型有關 * * @param str * @return */ implicit def strToInt(str: String) = str.toInt /** * 隱式類有如下幾個限制: * They must be defined inside of another trait/class/object. * They may only take one non-implicit argument in their constructor. * There may not be any method, member or object in scope with the same name as the implicit class. * Note: This means an implicit class cannot be a case class. * 隱式類的運作方式: * 隱式類的主構造函數只能有一個參數(有兩個以上並不會報錯,但是這個隱式類永遠不會被編譯器作為隱式類在隱式轉化中使用) * 且這個參數的類型就是將要被轉換的目標類型 * 隱式轉換類將包裹目標類型,隱式類的所有方法都會自動"附加"到目標類型上 * * @param origin 隱式類構造函數參數 */ implicit class ImpAdd(origin: Int) { def add(param: Int) = origin + param } }
ScalaDemo.scala
package com.donews.reynold //import com.donews.localspark.ImplVal import com.donews.localspark.ImplicitHelper.{ImpAdd, echo, strToInt} import com.donews.localspark.ImplVal.name /** * Created by reynold on 2017/3/16. */ object ScalaDemo /*extends ImplVal*/ { def main(args: Array[String]): Unit = { println(1.add(2)) //import com.donews.localspark.ImplicitHelper.strToInt 源碼一般放在上面 println(strToInt("1")) println(math.max("1", 2)) echo("hello")("word") //import com.donews.localspark.ImplVal.name echo("hello") //或者像下面這樣 //implicit val impl = "implicit" //echo("hello") } }
結果為:
3
1
2
hello,word
hello,reynold
隱式解析機制
即編譯器是如何查找到缺失信息的,解析具有以下兩種規則:
1.首先會在當前代碼作用域下查找隱式實體(隱式方法 隱式類 隱式對象)
2.如果第一條規則查找隱式實體失敗,會繼續在隱式參數的類型的作用域里查找(如上面代碼中的extends部分)
類型的作用域是指與該類型相關聯的全部伴生模塊,一個隱式實體的類型T它的查找范圍如下:
(1)如果T被定義為T with A with B with C,那么A,B,C都是T的部分,在T的隱式解析過程中,它們的伴生對象都會被搜索
(2)如果T是參數化類型,那么類型參數和與類型參數相關聯的部分都算作T的部分,比如List[String]的隱式搜索會搜索List的
伴生對象和String的伴生對象
(3) 如果T是一個單例類型p.T,即T是屬於某個p對象內,那么這個p對象也會被搜索
(4) 如果T是個類型注入S#T,那么S和T都會被搜索
參考:
http://m.2cto.com/kf/201603/493264.html
https://my.oschina.net/aiguozhe/blog/35968
http://www.cnblogs.com/MOBIN/p/5351900.html
http://blog.csdn.net/oopsoom/article/details/24643869
