从JAVA到Scala(三):implicit的三种用法

对scala的隐式参数又爱又恨,既强大得让人欢呼雀跃,但繁琐的机制与晦涩的语法又让人望而却步,总结起来,implicit一共有三种用法,一种比一种强大,这里就不讲太深奥的理论,直接进入应用场景实战。

1. 默认参数值

首先,需要注意的是,在方法参数上添加implicit关键字对方法几乎没有任何影响,原来的调用方式依旧。

其次,implicit作为参数声明时,只能作为方法的唯一参数,是的,你没看错,唯一的参数,还有每个方法也只能声明一个参数!如果混在一起,那么它几乎没有作用,因为每一次调用时你都必须指定方法的所有参数。当然,scala提供了完美的解决办法,请看下面的例子:

test("隐式参数必须独立声明") {
    //  调用时无法省略参数
    def add(implicit a: Int, b: Int): Int = a + b
    //  一定要作为最后一个参数
    def plus(a: Int)(implicit b: Int): Int = a + b
    //  声明隐式参数,不需要名称相同,只能类型相同就可以了
    implicit val c: Int = 10
    //  单元测试
    assertResult(plus(5))(15)
}

从上面的例子可以得出如下结论:
1. 通过高阶函数的方法,隐式参数可以和其他参数一起合作,但受限于调用方式,必须作为函数的最后一个参数;
2. 声明隐式参数时,并不需要采用与函数参数一样的名称,只要类型相同即可;

2. 参数类型转换

在方法的调用中,实参的类型有时难以匹配形参的类型,此时需要可以利用隐式方法进行自动转换

 test("隐式方法转换类型") {
    //  调用的方法,并不需要声明为隐式参数
    def plus(a: Int, b: Int): Int = a + b
    //  定义转换函数
    implicit def stringToInt(s: String): Int = Integer.parseInt(s)
    assertResult(plus("3", "5"))(8)
  }

从上面的例子中,我们可以看出:
1. 调用的方法不需要携带隐式参数,适用于所有的方法;
2. 定义转换函数后,大大增强了方法参数的适配性;
3. 隐式函数查找的作用域跟隐式参数的作用域一模一样;

3. 动态添加属性与方法

除了可以批量赋值默认参数,以及动态转换函数外,implicit最强大的地方还在于能为每种类型动态添加属性与方法,如下:

test("动态添加属性与方法") {
    //  参数就是添加属性与方法的类型
   implicit def strFile(dir: String) = new {
      //  动态添加属性
      val isDir:Boolean = true
      //  动态添加方法
      def listDir(): List[File] = {
        val d = new File(dir)
        //  _只有作为参数时才能省略,作为主体时不能省略
        d.listFiles().filter(_.isDirectory).toList
      }
    }
    assert("/".listDir().size > 0)
    assert("/".isDir)
}

这个功能简直强大到吓人,任意类型一律通杀,无视类型的声明是否是不变模型(final),无视类型是自定义还是系统内置。有了这样的机制,写出一万公里长的链式代码也是易如反掌。

4. 隐式作用域

为了找到相关的隐式参数与方法,scala会按如下优先级查找相关的隐式声明:
1. 在当前函数调用的作用域及父作用域内;
2. 在声明隐式参数类型的伴生作用域内;

结论

简简单单的implicit关键字,对Scala的功能增强几乎是天翻地覆,只有理解了implicit,尤其是第三种用法,才能理解如同天书一样的DSL代码(尤其是初次使用的JAVA程序员),强烈推荐《深入理解Scala》(这本书翻译得不太好,但内容很有深度)进一步阅读。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值