Scala隱式轉換與隱式引數

541732025發表於2016-02-24
我們有時需要類A具有類B的方法,可以自定義一個隱式轉換,將類A轉換為類B,在引入這個隱式轉換的作用域,使用類A就相當於使用了類B,
這樣就達到了增強類A功能的目的
。類似於裝飾模式。

點選(此處)摺疊或開啟

  1. class RichFile(val file:File){
  2.    def read = Source.fromFile(file.getPath()).mkString
  3. }
  4.  
  5. object Context{
  6.     implicit def file2RichFile(file:File)= new RichFile(file) //File -> RichFile,必須有implicit關鍵字
  7. }

  8. object Hello_Implicit_Conversions {

  9.   def main(args: Array[String]) {
  10.         import Context.file2RichFile //在當前作用域引入隱式轉換
  11.      println(new File("D:\\hello.txt").read)  //File本身是沒有read方法的,需要隱式轉換為自定義的RichFile
  12.   }
  13. }

隱式引數,最直觀的是,引數前面有implicit關鍵字,編譯器會在作用域範圍內查詢誰是implict型別的值,如果有,則作為預設值。

點選(此處)摺疊或開啟

  1. object Context_Implicits{
  2.     implicit val default:String = "Flink" //存在一個隱式值
  3. }
  4.  
  5. object Param{
  6.    def print(content:String)(implicit language:String){
  7.       println(language+":"+content)
  8.    }
  9. }
  10. object Implicit_Parameters {

  11.   def main(args: Array[String]) {
  12.     Param.print("Spark")("Scala")
  13.      
  14.     import Context_Implicits._ //從作用域範圍內或者Object伴生物件中查詢隱式引數
  15.     Param.print("Hadoop") //使用隱式引數
  16.   }
  17. }

隱式引數下的隱式轉換

object Implicit_Conversions_with_Implicit_Parameters {
  def main(args: Array[String]) {
    def bigger[T](a: T, b: T)(implicit ordered: T => Ordered[T]) //將匿名函式賦值給ordered變數,該隱式引數將T型別轉換為Ordered[T]型別
        = if (a > b) a else b //Ordered實現了<, >等
    println(bigger(4,3))
    println(bigger(4.2,3))
    println(bigger("Spark","Hadoop"))
  }
}

上下文界定中的隱式引數
class Pair_Implicits[T: Ordering](val first: T, val second: T){ //Ordering是泛型,上下文界定說明,只要存在T:Ordering ,就會存在一個隱式值Ordering[T]
  def bigger(implicit ordered: Ordering[T]) =
    if (ordered.compare(first, second) > 0) first else second
}
class Pair_Implicitly[T: Ordering](val first: T, val second: T){
    def bigger =if (implicitly[Ordering[T]].compare(first, second) > 0)  //implicitly提取出執行時上下文界定的例項
            first else second
}
class Pair_Implicitly_Odereded[T: Ordering](val first: T, val second: T){
    def bigger ={
      import Ordered._
      if (first > second) first else second //將Ordering[T]轉換為Ordered[T],可以直接使用>
    }    
}

object Context_Bounds_Internals {
  def main(args: Array[String]){
    println(new Pair_Implicits(7, 9).bigger)
    println(new Pair_Implicitly(7, 9).bigger)
    println(new Pair_Implicitly_Odereded(7, 9).bigger)
  }
}

隱式類:對類的功能增強

點選(此處)摺疊或開啟

  1. object Context_Helper{
  2.     implicit class FileEnhancer(file : File){
  3.         def read = Source.fromFile(file.getPath).mkString
  4.     }
  5.     implicit class Op(x:Int){
  6.          def addSAP(second: Int) = x + second
  7.     }
  8. }
  9. object Implicits_Class {
  10.   def main(args: Array[String]){
  11.     import Context_Helper._
  12.     println(1.addSAP(2))
  13.     println(new File("E:\\Test.txt").read)
  14.     
  15.   }
  16. }

隱式物件

點選(此處)摺疊或開啟

  1. abstract class Template[T] {
  2.       def add(x: T, y: T): T
  3.     }
  4. abstract class SubTemplate[T] extends Template[T] {
  5.       def unit: T
  6.     }
  7. object Implicits_Object {

  8.   def main(args: Array[String]) {
  9.      implicit object StringAdd extends SubTemplate[String] {
  10.         override def add(x: String, y: String) = x concat y
  11.         override def unit: String = ""
  12.       }
  13.       implicit object IntAdd extends SubTemplate[Int] {
  14.         override def add(x: Int, y: Int) = x + y
  15.         override def unit: Int = 0
  16.       }
  17.       def sum[T](xs: List[T])(implicit m: SubTemplate[T]): T = //m為隱式物件,根據T的具體型別引入相應的隱式物件
  18.      
  19.       if (xs.isEmpty) m.unit
  20.       else m.add(xs.head, sum(xs.tail)) 

  21.       println(sum(List(1, 2, 3, 4, 5))) //入IntAdd隱式物件
  22.       println(sum(List("Scala", "Spark", "Kafka"))) //引入StringAdd隱式物件
  23.     
  24.   }

  25. }

隱式轉換內幕

點選(此處)摺疊或開啟

  1. class RicherFile(val file:File){
  2.    def read = Source.fromFile(file.getPath()).mkString
  3. }
  4.  
  5. class File_Implicits( path: String) extends File(path)
  6. object File_Implicits{
  7.     implicit def file2RicherFile(file:File)= new RicherFile(file) //File -> RicherFile
  8. }

  9. object Implicits_Internals {
  10.     def main(args: Array[String]) {

  11.         //因為類可以訪問伴生物件裡的所有內容,所以這裡不需要import
  12.         println(new File_Implicits("E:\\Test.txt").read) //當前作用域沒有import隱式引數,嘗試從類的伴生物件中查詢
  13.     }
  14. }

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28912557/viewspace-1993997/,如需轉載,請註明出處,否則將追究法律責任。

相關文章