Scala進階之隱式轉換作用域等問題

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

發佈了45 篇原創文章 · 獲贊 5 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章