Reputation: 97918
I expect the code below to print out 1
and 2
. But I get default
and default
. When I explicitly forward (?) the implicit value using the commented out code, I see the desired output. Can anyone explain how this works? Is what I'm trying impossible? I'm totally new to Scala. What should I read to understand this in depth?
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())
}
}
Upvotes: 0
Views: 286
Reputation: 1186
From the scala documentation of implicit, these are the two rules for determining value for an implicit parameter.
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.
So in your case, lets first see what happens when we use def create() = ToolCreator.create()
. Here, ToolCreator.create()
will call create
method of the companion object ToolCreator
which expects an implicit Context
def create()(implicit context: Context) = context.id.getOrElse("null")
Context
and we have a Context companion object which has a nice implicit variable defined. So that value will be picked up in the create
method.
object Context {
implicit val context = Context(Some("default"))
}
Now if we use the def create()(implicit context: Context) = ToolCreator.create()
, this create method is invoked from the
class ToolBuilder (id: String) {
implicit val context = Context(Some(id))
def extract() = ToolCreatorA.create()
}
As you can see, here before the create
method is invoked, it has a context variable available to be used as implicit. So that value will be picked up.
Useful links:
http://www.drmaciver.com/2008/03/an-introduction-to-implicit-arguments/
http://www.artima.com/pins1ed/implicit-conversions-and-parameters.html#21.5
Upvotes: 3