Scala implicitly

概述

implicitly 在 scala 2.8 被引入,定义在 scala.Predef 中:

@inline def implicitly[T](implicit e: T) = e 

implicitly 用法可以总结为如下:

  1. 理解 Implicit View
  2. 访问 Context Bound 引入的隐式参数
  3. 显式传递部分隐式参数

理解 Implicit View

Implicit View 即编译器将一次选择的目标类型进行转换,也可以称为隐式转换。

比如说 scala 为 Int 到 scala.runtime.RichInt 定义了隐式转换:

scala> 1: scala.runtime.RichInt
res0: scala.runtime.RichInt = 1

利用 implicitly,我们就可以获得 Int 到 scala.runtime.RichInt 的转换函数:

scala> val intToRichInt = implicitly[Int => scala.runtime.RichInt]
intToRichInt: Int => scala.runtime.RichInt = $$Lambda$1103/1825228532@438c9aa7


scala> intToRichInt(10)
res1: scala.runtime.RichInt = 10

implicitly 赋予了我们直接检查隐式转换的可能性,利用 implicitly 我们可以检查某些转换是否会发生。

访问 Context Bound 引入的隐式参数

Scala 2.8 为隐式参数引入了更简洁的语法,称为 context bound。简单来说,一个方法的类型参数是 A,并且需要一个类型为 M[A] 的隐式参数:

def foo[A](implicit ma: M[A])

那么这样的方法定义可以写成:

def foo[A: M]

语法 [A: M] 就是 context bound。

在 foo 方法中,我们可以用 implicitly 获得隐式参数的值:

def foo[A: M]{
    val ma = implicitly[M[A]]
}

显示传递部分隐式部分参数

我们知道如果参数列表前有 implicit,那么我们可以省略整个参数列表,由编译器帮我们补上。但是有时候我们也希望能够显式指定某些参数,剩下的参数才由编译器帮我们补上。

这可以利用 implicitly 完成,对于那些我们希望编译器补上的参数,我们直接传 implicitly;剩下的参数就可以显式指定了。

参考

  1. What is the Scala identifier “implicitly”?
  2. Programming in Scala

Previous post: 有括号方法和无括号方法区别