如何理解 Scala 隐式转换 隐式参数

本文通过实例详细解析Scala中的隐式转换和隐式参数功能,包括如何定义及使用这些特性来增强类的功能,特别是在Akka并发编程、SparkSQL等场景的应用。

隐式转换和隐式参数是 scala 非常有特色的功能,也是Java等其他编程语言没有的功能。

利用隐式转换 可以很方便地来丰富现有类的功能,在编写Akka并发编程、Spark SQL、Flink 等程序时 都会看到隐式转换和隐式参数的身影;但其实现方式有点绕,不太容量理解。

以下通过 Demo 来说明:

实现隐式转换方法的 Demo:

目的:File 类本身没有 read 方法,希望代码看起来像 File 有能直接调用的 read 方法一样;

实现步骤:1)定义隐式转换方法 File2RichFile (RichFile 含有 read 方法);2)导入隐式转换方法。

        然后即可实现目的。

原理:隐式转换方法的关键在于入参类型出参类型, 与方法名无关;

代码表面上是入参类型的对象 调用了 某方法,实际底层是出参类型的对象调用的那个方法,因为 入参类型的对象 被隐式转换成了 出参类型的对象。
具体就此 Demo 来说,File 调用 read 方法时,编译器发现此类本身并没有此方法,则会寻找并调用以 File 类为入参类型的隐式转换方法 File2RichFile,于是背地里 file 对象就被悄悄转成了 richFile 对象,richFile 有 read 方法的定义,于是编译通过。

class RichFile(file: File) {
    def read() = {
      Source.fromFile(file).mkString
    }
  }
  
  // 手动使用import来导入隐式转换: 
  //  1) 在object中定义隐式转换方法(使用implicit)
  //  2) 在需要用到隐式转换的地方,引入隐式转换(使用import)
  //  3) 自动调用隐式转化后的方法
  
//  object RichFile {
//    implicit def File2RichFile(file:File): RichFile = new RichFile(file)
//  }
//
//  def main(args: Array[String]) {
//    val file = new File("./data/1.txt")
//    
//    import RichFile.File2RichFile
//    
//    println(file.read())
//  }  

  
  // 在scala中,如果在当前作用域中有隐式转换方法,会自动导入隐式转换。
  // 自动导入隐式转换方法
// 此方法的关键在于入参类型和出参类型, 方法名无所谓
// 有此方法时, 如果入参类型的对象调用了自身没有的方法, 编译器则会尝试调用出参类型的方法
  implicit def File2RichFile(file:File): RichFile = new RichFile(file)


  def main(args: Array[String]) {
    val file = new File("./data/1.txt")
    
    println(file.read())
  }

隐式参数的 Demo, 原理与隐式转换类似,只是隐式参数调用处有显式指明 "implicit",则调用 quote 方法时不必传这种参数,但也可显式传参,编译器将优先取显式传参(编译器的优先级为: 传值 >隐式值>默认值):

  def quote(msg:String)(implicit delimiter:(String, String)) = {
    delimiter._1 + msg + delimiter._2
  }
  
  // 和隐式转换一样,可以使用import手动导入隐式参数
  
//  object ImplicitParam {
//    implicit val DELIMITER = ("<<<", ">>>")
//  }
//
//  def main(args: Array[String]) {
//    import ImplicitParam.DELIMITER
//    
//    println(quote("metacognition"))
//  }
  
  // 自动隐式转换参数
  //  如果在当前作用域定义了隐式值,会自动进行导入
  // 参数名无所谓,调用 quote 方法时 隐式入参类型为 (String, String),编译器即会寻找并使用此类型的隐式参数
  implicit val DELIMITER = ("<<<", ">>>")

  def main(args: Array[String]) {
    
    println(quote("metacognition"))
  }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值