zoukankan      html  css  js  c++  java
  • Scala进阶之路-Scala高级语法之隐式(implicit)详解

              Scala进阶之路-Scala高级语法之隐式(implicit)详解

                                      作者:尹正杰

    版权声明:原创作品,谢绝转载!否则将追究法律责任。

      我们调用别人的框架,发现少了一些方法,需要添加,但是让别人为你一个人添加是不现实的,因此很多很多时候需要我们自己动手。掌握implicit的用法是阅读Spark源码的基础,也是学习Scala其它的开源框架的关键,implicit可分为隐式参数,隐式转换类型以及隐式类三种类型。

    一.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       *     定义一个隐式值,编译器在查找隐式值的时候,不能出现歧义,也就是说,编译器在编译代码的时候,不能找到
    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中的隐式类型转换

     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中的隐式类

     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文件对象里面的内容如下:
    ${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  */

     

  • 相关阅读:
    阿里云ECS安装sqlserver,本地无法连接问题排查思路
    1433端口无法连接(sql server 数据库无法访问问题)解决思路
    开源框架 电商参考系统
    版本控制工具 Git 只下载开源项目的某个文件夹
    VUE 在idea中的运行项目
    开源框架 Java Guns 03 数据库替换为sqlite
    SQL Server 用ip地址登录 127.0.0.1
    开源框架 UI框架
    电商 电商系统汇总
    电商 平台汇总
  • 原文地址:https://www.cnblogs.com/yinzhengjie/p/9376317.html
Copyright © 2011-2022 走看看