Reputation: 4359
I'm working on coming up to speed with Scala and am a little confused about usage of the keyword "implicit."
I think I understand the notion of implicit parameters, where the parameters are not explicitly passed in, Scala will search for a value of the correct type (within the calling scope).
I'm confused with the use of "implicit val."
Consider the following code snippet:
case class DemoApp() {
implicit val foo = CustomerFoo()
}
Does this have to do with parameters passed into the DemoApp() class constructor?
Can someone please clarify?
Thx, JohnB
Upvotes: 3
Views: 4019
Reputation: 369420
think I understand the notion of implicit parameters, where the parameters are not explicitly passed in,
This is just the other side of the coin.
Scala will search for a value of the correct type (within the calling scope).
Yes, but it will not just take any random value. Only values that are explicitly marked implicit
.
There are four uses of an implicit
modifier, which are related in pairs.
One pair is related to implicit parameters. When applied to a parameter in a parameter list, implicit
means "this argument does not need to be supplied explicitly, it can be searched in the context of the call". When applied to a val
or an object
, in turn, it means "this value can be passed as an implicit argument".
The other pair is related to implicit conversions. When implicit
is applied to a method definition of a method with one parameter, it means "whenever you need a value of the return type, but you only have a value of the parameter type, you can use this method to convert from the argument value to the return value".
E.g. if I have something like this:
implicit def string2Tuple2(s: String): (Int, Int) = {
val l = s.split(",")
(l(0).toInt, l(1).toInt)
}
Then, whenever Scala expects a (Int, Int)
, I can also pass a String
instead, and Scala knows that it can call string2Tuple
to convert it:
val m = Map.empty[Int, Int]
m + "2,3"
//=> val res1: scala.collection.immutable.Map[Int,Int] = Map(2 -> 3)
This is of course a stupid example. A more useful example is the enrich-my-library idiom, where we create a new class that augments an existing class with some new functionality, and then provide an implicit conversion from the old type to the enriched type:
class HelloString(s: String) {
val hello = "Hello " + s + " World"
}
implicit def string2HelloString(s: String) = new HelloString(s)
"beautiful".hello
//=> val res2: String = Hello beautiful World
This is where the second use for the implicit
modifier comes in. An implicit
class is simply syntactic sugar for a wrapper class + an implicit conversion, meaning the above is exactly equivalent to:
implicit class string2HelloString(s: String) {
val hello = "Hello " + s + " World"
}
There you have it, the four uses of the implicit
modifier in two related pairs.
Upvotes: 8