Implicit parameters allow us to write code where one or more parameters can be supplied automatically by Scala in a similar way to dependency injection works.
For example, let’s assume we have a Calculator class (below) which we want to supply to functions/methods in our application
class Calculator { def add(a : Int, b : Int) = a + b; def subtract(a : Int, b : Int) = a - b; }
In this instance I’m going create the equivalent of a singleton to the class, the val name doesn’t really matter in the code I’m demonstrating as Scala will simply locate the matching type within the MyImplicits object.
object MyImplicits { implicit val calculator = new Calculator(); }
To use this singleton instance we simply import the MyImplicits._ into our code. Here’s an example of using such code. Notice how the calls to the add and subtract functions in the main method do not need to supply the implicit parameter. This is supplied by Scala for us.
object Main { import MyImplicits._ def add(implicit c : Calculator) : Unit = { println(c.add(1, 2)); } def subtract(a : Int, b : Int)(implicit c : Calculator) : Unit = { println(c.subtract(a, b)); } def main(args: Array[String]) : Unit = { val i = add val s = subtract(10, 2) } }
Of course, using such code means we could supply another instance of the Calculator class to either of the add or subtract methods if we wished or change the code to work with traits and implementations which would obviously allow us to import different implementations of the trait. Here’s the code from above but using a trait for the implicit argument
trait Calc { def add(a : Int, b : Int) : Int; def subtract(a : Int, b : Int) : Int; } class Calculator extends Calc { override def add(a : Int, b : Int) = a + b; override def subtract(a : Int, b : Int) = a - b; } object MyImplicits { implicit val calculator = new Calculator(); } object Main { import MyImplicits._ def add(implicit c : Calc) : Unit = { println(c.add(1, 2)); } def subtract(a : Int, b : Int)(implicit c : Calc) : Unit = { println(c.subtract(a, b)); } def main(args: Array[String]) : Unit = { val i = add; val s = subtract(10, 2); } }