如何间接传递隐式参数

How to pass an implicit argument indirectly

我希望下面的代码打印出 12。但是我得到 defaultdefault。当我使用注释掉的代码显式转发 (?) 隐式值时,我看到了所需的输出。谁能解释这是如何工作的?我正在尝试的是不可能的吗?我是 Scala 的新手。我应该阅读哪些内容才能深入理解这一点?

case class Context(id: Option[String])
object Context {
  implicit val context = Context(Some("default"))
}

class ToolBuilder (id: String) {
  implicit val context = Context(Some(id))
  def extract() = ToolCreatorA.create()
}

case class ToolCreatorA(id: String)
object ToolCreatorA {
  def create() = ToolCreator.create()
  //def create()(implicit context: Context) = ToolCreator.create()
  object ToolCreator {
    def create()(implicit context: Context) = context.id.getOrElse("null")
  }
}

object Main {
  def main(args: Array[String]): Unit = {
    println(new ToolBuilder("1").extract())
    println(new ToolBuilder("2").extract())
  }
}

来自scala documentation of implicit,这是确定隐式参数值的两条规则。

First, eligible are all identifiers x that can be accessed at the point of the method call without a prefix and that denote an implicit definition or an implicit parameter.

Second, eligible are also all members of companion modules of the implicit parameter’s type that are labeled implicit.

所以在你的情况下,让我们先看看当我们使用 def create() = ToolCreator.create() 时会发生什么。这里,ToolCreator.create() 将调用伴随对象 ToolCreatorcreate 方法,它需要一个隐式的 Context def create()(implicit context: Context) = context.id.getOrElse("null")

  1. 现在我们的第一条规则说,该方法将在方法调用发生之前在它有权访问的所有变量中查找隐式参数。我们看到此时没有可用的隐式变量。
  2. 那么第二条规则就是,在隐式类型的伴生对象中寻找隐式变量。在我们的例子中,隐式是 Context 类型,我们有一个 Context 伴随对象,它定义了一个很好的隐式变量。因此该值将在 create 方法中被拾取。 object Context { implicit val context = Context(Some("default")) }
  3. 现在如果我们使用 def create()(implicit context: Context) = ToolCreator.create() ,这个创建方法是从

    调用的

    class ToolBuilder (id: String) { implicit val context = Context(Some(id)) def extract() = ToolCreatorA.create() }

  4. 如您所见,在调用 create 方法之前,它有一个上下文变量可用作隐式变量。因此该值将被拾取。

有用链接:

  1. Understanding implicit in Scala

  2. http://www.drmaciver.com/2008/03/an-introduction-to-implicit-arguments/

  3. http://www.artima.com/pins1ed/implicit-conversions-and-parameters.html#21.5