zoukankan      html  css  js  c++  java
  • Scala 进阶(2)—— implicit 用法:隐式转换

    1. 转换接收端

    在 Scala 中,implicit 的一个常见用法,是作为方法调用的接收端,如果觉得这种说法过于晦涩的话,我的理解是:

    • implicit 可以动态地为目标对象增加函数。

    我们首先看一段例子:

      implicit class JsonPatchExt(underlying: playJson.JsonPatch) {
    
        /**
         * Transforms a playJsonPatch [[playJson.JsonPatch]] into a common [[Patch]] used in this project.
         *
         * @return a list of [[Patch]]es representing the list of diffson operations.
         */
        def toCommonPatch: Seq[Patch] = underlying.ops.collect {
          case Add(path, value) => Patch.add(path.serialize, Some(value))
          case Replace(path, value, _) => Patch.replace(path.serialize, Some(value))
          case Remove(path, _) => Patch.remove(path.serialize)
        }
      }

    这里我们定义了一个 implicit class。

    在原先的 source code 中,playJson.JsonPatch 这个类,并没有定义 toCommonPatch 这个方法,而我们通过 implicit class 为 JsonPatch 增加了 toCommonPatch 方法。

    2. 原理

    它是怎么做到的?

    假设现在有个调用端,有一个 jsPatch 的 JsonPatch 对象,用了 jsPatch.toCommonPatch 方法。

    在 Scala 的编译过程中,编译器依次做了以下这些事情:

    1. 根据方法签名,在 JsonPatch 类中寻找一个 toCommonPatch 方法,并且接受空的参数列表,失败。
    2. 寻找一个潜在的,作用域中拥有从 JsonPatch -> XXX 类的隐式转换,并且这个 XXX 类具有需要的方法签名,找到了 JsonPatchExt 类。
    3. 进行一次类型转换,将目标对象 jsPatch 转为相应的 JsonPatchExt 对象,调用其 toCommonPatch 方法,类似于:transform(jsPatch).toCommonPatch,当然,transform 的实现被编译器隐藏了。

    3. 个人习惯/代码规范

    针对这种 implicit class 的定义,一般来说,我个人习惯遵循以下两个原则:

    • 根据适用的作用域,定义在 伴生对象 object 内部,或者 package object 中。
    • 类名一般定义为 XxxExt 或者 RichXxx。
  • 相关阅读:
    一个总成本花费100W的失败项目的小小反省
    从绝望中寻找希望
    一个合格程序员该做的事情——你做好了吗?
    Go to 北京!
    深入浅出Oracle分析函数
    最适合web开发人员使用的速查表
    采用axis2c进行webservice发布的流程4在生成的代码中添加事务处理逻辑
    采用axis2c进行webservice发布的流程1
    rhel6.0及centos6.0 忘记root密码解决办法
    采用axis2c进行webservice发布的流程3通过wsdl文件,自动生成C的服务端代码
  • 原文地址:https://www.cnblogs.com/jing-an-feng-shao/p/14790305.html
Copyright © 2011-2022 走看看