Scala進階之路-Scala高級語法之隱式(implicit)詳解

          Scala進階之路-Scala高級語法之隱式(implicit)詳解java

                                  做者:尹正傑框架

版權聲明:原創做品,謝絕轉載!不然將追究法律責任。函數

 

 

  咱們調用別人的框架,發現少了一些方法,須要添加,可是讓別人爲你一我的添加是不現實的,所以不少不少時候須要咱們本身動手。掌握implicit的用法是閱讀Spark源碼的基礎,也是學習Scala其它的開源框架的關鍵,implicit可分爲隱式參數,隱式轉換類型以及隱式類三種類型。學習

 

一.Scala中的隱士參數spa

 1 /*
 2 @author :yinzhengjie
 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Scala%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
 4 EMAIL:y1053419035@qq.com
 5 */
 6 package cn.org.yinzhengjie.scalaImplicit
 7 
 8 object ScalaImplicit {
 9 
10     /**
11       *     定義一個隱式值,編譯器在查找隱式值的時候,不能出現歧義,也就是說,編譯器在編譯代碼的時候,不能找到
12       * 兩個類型一致的隱式值,否則編譯器是會編譯不經過的!
13       */
14     implicit val default:Int = 500
15 
16     /**
17       * @param Name  : 此處咱們將Name設置爲隱士的參數
18       */
19     def sayHello(implicit Name:String = "YinZhengJie") = {
20         println(s"I'm ${Name},I love Beijing !")
21     }
22 
23     /**
24       * @param x    : 柯里化函數(Currying)的第一個參數
25       * @param y    :柯里化函數(Currying)的第二個參數,其類型爲一個隱式的參數喲
26       * @return     : 返回值類型爲Int
27       */
28     def add(x:Int)(implicit y:Int):Int={
29         x + y
30     }
31 
32     /**
33       *     方法的參數若是有多個隱式參數的話,只須要使用一個implicit關鍵字便可,隱式參數列表必須放在方法的參數列表後面
34       */
35     def sum(a:Int)(implicit b:Int,c:Int):Int={
36         a + b + c
37     }
38 
39     def main(args: Array[String]): Unit = {
40 
41         sayHello("yinzhengjie")
42 
43         /**
44           *     sayHello方法參數是隱式參數,若是你沒有給sayHello傳遞參數的話,編譯器在編譯的時候會自動從當前的上下文中
45           * 找一個隱式值(符合參數類型的隱式值),若是有則使用,若是沒有就使用sayHello方法參數的默認值,指的注意的是,當一
46           * 各種中出現了多個implicit變量時,貌似默認值也很差使了!當前的類我就定了2個implicit變量就是一個很好的例子!
47           */
48 //        sayHello
49 
50         implicit val msg:String = "尹正傑"
51         sayHello
52 
53         /**
54           * 在調用柯里化函數(Currying)的時候,咱們僅僅出入了第一個參數,第二個參數默認就是類中的成員變量用implicit修飾的default的值。
55           */
56         val res = add(20)
57         println(s"res =====》 ${res}")
58 
59 
60         /**
61           * 原本須要傳入3個參數的,可是咱們就傳了一個,其餘兩個參數就會默認使用類中的成員變量用implicit修飾的default的值。
62           */
63         val res2 = sum(10)
64         println(s"res2 =====》 ${res2}")
65     }
66 }
67 
68 
69 
70 /*
71 以上代碼輸出結果以下:
72 I'm yinzhengjie,I love Beijing !
73 I'm 尹正傑,I love Beijing !
74 res =====》 520
75 res2 =====》 1010
76  */

 

二.Scala中的隱式類型轉換scala

 1 /*
 2 @author :yinzhengjie
 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Scala%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
 4 EMAIL:y1053419035@qq.com
 5 */
 6 package cn.org.yinzhengjie.scalaImplicit
 7 
 8 object ScalaImplicit {
 9 
10     /**
11       * 使用關鍵字implicit定義一個隱式方法。
12       */
13     implicit def doubleToInt(double: Double):Int = {
14         println("====== 調用了方法:doubleToInt ======")
15         double.toInt
16     }
17     /**
18       * 使用關鍵字implicit定義一個隱式函數。
19       */
20     implicit val doubleToInt2 = (double:Double) => {
21         println("====== 調用了函數:doubleToInt2 ======")
22         double.toInt
23     }
24 
25 
26     def main(args: Array[String]): Unit = {
27 
28         /**
29           *     year是一個Int類型的變量,可是賦值的確實一個浮點型數字,此刻編譯器會在當前上下文中找一個
30           * 隱式轉換,找一個能把浮點型變成Int類型的隱式轉換的函數或者方法,若是有函數實現了這個功能就優先
31           * 調用函數的功能,若沒有函數實現該功能就回去找是否有方法實現了該功能!若是函數或者方法都沒有實現
32           * 該功能編譯器是會報錯的!
33           */
34         val year:Int = 2018.7
35         println(s"year的結果是: ${year}")
36     }
37 }
38 
39 
40 /*
41 以上代碼輸出結果以下:
42 ====== 調用了函數:doubleToInt2 ======
43 year的結果是: 2018
44  */

 

三.Scala中的隱式類code

 1 /*
 2 @author :yinzhengjie
 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Scala%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
 4 EMAIL:y1053419035@qq.com
 5 */
 6 package cn.org.yinzhengjie.scalaImplicit
 7 
 8 import java.io.File
 9 
10 import scala.io.Source
11 
12 
13 
14 object ScalaImplicit {
15     /**
16       * 定義隱式類,只能在靜態對象(使用Object修飾)中使用
17       */
18     implicit class FileRead(file:File){
19         def myRead() = Source.fromFile(file).mkString
20     }
21 
22     def main(args: Array[String]): Unit = {
23         val file = new File("D:\\10.Java\\IDE\\yhinzhengjieData\\Scala\\1.txt")
24         val lineCounts =  file.myRead()
25         println(s"file文件對象裏面的內容以下:\n${lineCounts}")
26     }
27 }
28 
29 
30 /*
31 以上代碼輸出結果以下:
32 file文件對象裏面的內容以下:
33 hello wolrd
34 hello wolrd
35 hello wolrd
36 hello wolrd
37 hello wolrd
38 hello wolrd
39 hello wolrd
40 hello wolrd
41 hello wolrd
42 hello wolrd
43 hello wolrd
44 hello wolrd
45 hello wolrd
46 hello wolrd
47 hello wolrd
48 hello wolrd
49 hello wolrd
50 hello wolrd
51  */

 

 

 

四.小試牛刀(封裝File對象,新增lineCount方法,用來統計文件的行數,要求使用隱式方法對象

 1 /*
 2 @author :yinzhengjie
 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Scala%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
 4 EMAIL:y1053419035@qq.com
 5 */
 6 package cn.org.yinzhengjie.scalaImplicit
 7 
 8 import java.io.{BufferedReader, File, FileReader}
 9 
10 
11 /**
12   * 自定義一個RichFile類,封裝File類
13   */
14 class RichFile(file:File){
15     /**
16       * 定義方法返回文件的記錄行數
17       */
18     def linesCount():Int={
19         val fileReader = new FileReader(file)
20         val bufferReader = new BufferedReader(fileReader)
21 
22         var sum = 0
23         try {
24             var line = bufferReader.readLine()
25             while (line != null) {
26                 sum += 1
27                 line = bufferReader.readLine()
28             }
29         } catch {
30             case _: Exception => sum
31         } finally {
32             fileReader.close()
33             bufferReader.close()
34         }
35         sum
36     }
37 }
38 
39 
40 object ScalaImplicit {
41     /**
42       * 定義一個隱式方法,將File類型轉換成RichFile類型。
43       */
44     implicit def fileToRichFile(file: File) = {
45         new RichFile(file)
46     }
47 
48     def main(args: Array[String]): Unit = {
49         val file = new File("D:\\10.Java\\IDE\\yhinzhengjieData\\Scala\\1.txt")
50 
51        val lineCounts =  file.linesCount()
52         println(s"file文件對象裏面的行數是:${lineCounts}")
53     }
54 }
55 
56 
57 /*
58 以上代碼輸出結果以下:
59 file文件對象裏面的行數是:18
60  */
相關文章
相關標籤/搜索