Implicit is another exciting and powerful feature introduced by Scala, and it can refer to two different things:
- A value that can be automatically passed
- Automatic conversion from one type to another
- They can be used for extending the capabilities of a class
Actual automatic conversion can be accomplished with implicit def, as seen in the following example (supposing you are using the Scala REPL):
scala> implicit def stringToInt(s: String) = s.toInt
stringToInt: (s: String)Int
Now, having the preceding code in my scope, it's possible for me to do something like this:
scala> def add(x:Int, y:Int) = x + y
add: (x: Int, y: Int)Int
scala> add(1, "2")
res5: Int = 3
scala>
Even if one of the parameters passed to add() is a String (and add() would require you to provide two integers), having the implicit conversion in scope allows the compiler to automatically convert from String to Int. Obviously enough, this feature could be quite dangerous, because it makes the code less readable; moreover, once an implicit conversion is defined, it's not easy to tell the compiler when to use it and when to avoid using it.
The first type of implicit is a value that can automatically pass an implicit parameter. These parameters are passed while calling a method like any normal parameter, but Scala's compiler tries to fill them automatically. If Scala's compiler fails to automatically fill these parameters, it will complain. The following is an example to demonstrate the first type of implicit:
def add(implicit num: Int) = 2 + num
By this, you are asking the compiler to look for an implicit value for num, if not provided during calling the method. You can define implicit value to the compiler like this:
implicit val adder = 2
Then, we can simply call the function like this:
add
Here, no parameter is passed, so Scala's compiler will look for implicit value, which is 2, and then return 4 as the output of the method calling. However, a lot of other options have evolved a questions such as:
- Can a method contain both an explicit and an implicit parameter? The answer is YES. Let's see an example on Scala REPL:
scala> def helloWold(implicit a: Int, b: String) = println(a, b)
helloWold: (implicit a: Int, implicit b: String)Unit
scala> val i = 2
i: Int = 2
scala> helloWorld(i, implicitly)
(2,)
scala>
- Can a method contain more than one implicit parameter? The answer is YES. Let's see an example on Scala REPL:
scala> def helloWold(implicit a: Int, b: String) = println(a, b)
helloWold: (implicit a: Int, implicit b: String)Unit
scala> helloWold(i, implicitly)
(1,)
scala>
- Can an implicit parameter be explicitly provided? The answer is YES. Let's see an example on Scala REPL:
scala> def helloWold(implicit a: Int, b: String) = println(a, b)
helloWold: (implicit a: Int, implicit b: String)Unit
scala> helloWold(20, "Hello world!")
(20,Hello world!)
scala>
What happens if more implicits are contained in the same scope and how are implicits resolved? Is there any order to how implicits are resolved? To get to know the answer to these two questions, refer to this URL at http://stackoverflow.com/questions/9530893/good-example-of-implicit-parameter-in-scala.
In the next section, we will discuss generics in Scala with some examples.