1.隱式轉換作用域
關於隱式轉換查找的順序問題:
1. 簡單查找
class Implicits {
implicit val content = "Java Hadoop"
}
object Implicits {
implicit val content = "Scala Spark"
}
object ImplicitsAdvanced {
def main(args: Array[String]): Unit = {
def printContent(implicit content: String) = println(content)
implicit val content = "I love spark"
import Implicits._
printContent
}
printContent 的隱式參數是String類型,所以會找String類型的隱式參數,
上面例子上有三個可能,"Java Hadoop", "Scala Spark", "I love spark"
結果是
I love spark
即它會先在main這個大括號裏找滿足要求的String類型隱式參數,找到就用,優先級最高。
只有找不到了纔會去導入的類裏找,把implicit val content = "I love spark"註釋掉後
結果是
Scala Spark
說明它要找的是伴生對象裏的隱式參數,而非類裏面的隱式參數!
如果再加上一個隱式參數如下
object ImplicitsMsg {
implicit val content = "Kafak Zookeeper"
}
導入時這樣導入
import ImplicitsMsg.content
結果是
Kafak Zookeeper
說明都是導入的情況下,優先選擇具體的,通配符導入的優化級較低。
2.複雜查找
查找時如果在main方法裏找不到,在導入的類的伴生對象裏也找不到怎麼辦呢?
class ImplicitsMsg{
val content = "ImplicitsMsg class"
}
object ImplicitsMsg {
val content = "ImplicitsMsg object"
}
class ImplicitsChild extends ImplicitsMsg{
override implicit val content = "ImplicitsChild class"
}
object ImplicitsChild extends ImplicitsMsg{
override implicit val content = "ImplicitsChild object"
}
object ImplicitsAdvanced {
def main(args: Array[String]): Unit = {
def printContent(implicit content: String) = println(content)
// implicit val content = "I love spark"
import ImplicitsMsg._
println("=========")
printContent
}
}
輸出的結果是報錯,這與王老師講的不一樣,老師說:
“如果當前類的伴生對象無法找到相關的功能,則會到該類相關的所有類和接口的伴生對象中去查找”
我發現如果導入的類的伴生對象裏沒有相應的隱式參數的話,在IDEA中導入的語句
import ImplicitsMsg._就是灰色的,說明根本不可能導入其子類的隱式參數content
也就意味着查找時只是查找導入的那一層的伴生對象,不會去查找其子類或者接口的隱式類型。
2.最佳實踐
在Spark源碼中隱式轉換在伴生對象裏面到處可見,沒見過使用import導入的方式,
這是要學習的地方,以後寫隱式轉換就寫在類的伴生對象裏面。
業界實踐,如果你要改變一個類的功能,那就寫在伴生對象裏面。
這對以後代碼升級有好處。(現在理解還不深 -_-! )
3.蘑菇雲代碼
package com.dt.scala.moguyun
/**
* 1,當我們使用一個類型的使用如果當前類型無法直接找到合適的方法,則會到其伴生對象中查找隱式功能;
* 2,如果當前類的伴生對象無法找到相關的功能,則會到該類相關的所有類和接口的伴生對象中去查找
*/
class Implicits(x: Int) {
implicit val content = "Java Hadoop"
def printValue = {
val x = 100
println(x)
Map
}
}
object Implicits {
implicit val content = "Scala Spark"
implicit def int2String(x: Int) = x.toString()
//命名時爲了方便2是to的意思
implicit def file2RicherFile(file: java.io.File) = new RicherFile(file)
//有時還需轉換回來
implicit def richerFile2File(richerFile: RicherFile) = richerFile.file
}
class ImplicitsMsg {
val content = "ImplicitsMsg class"
}
object ImplicitsMsg {
val content = "ImplicitsMsg object"
}
class ImplicitsChild extends ImplicitsMsg {
override implicit val content = "ImplicitsChild class"
}
object ImplicitsChild extends ImplicitsMsg {
override implicit val content = "ImplicitsChild object"
}
class RicherFile(val file: java.io.File) {
def dtspark = println("Welcome to dtspark World ")
}
object ImplicitsAdvanced {
def main(args: Array[String]): Unit = {
def printContent(implicit content: String) = println(content)
// implicit val content = "I love spark"
import Implicits._
// import ImplicitsMsg._
println("=========")
printContent
val file = new java.io.File(".")
file.dtspark
//implicitly是判斷隱式類型的值,如下是求出String的隱式值
println(implicitly[String])
}
}
結果
Scala Spark
Welcome to dtspark World
Scala Spark
以上內容來自[DT大數據夢工廠]首席專家Spark專家王家林老師的課程分享。感謝王老師的分享,更多精彩內容請掃描關注[DT大數據夢工廠]微信公衆號DT_Spark