Scala implicits are a great tool to remove code duplication and convert objects from different domains. However, we need to learn not to abuse them: by hiding code they can make the code more concise but more cryptic at the same time.
In order to use implicits efficiently, we need to know how the compiler tries to search and apply them:
– Making rule: an implicit needs to be identified by the implicit keyword.
– Scope rule: an implicit needs to be in scope as single identifier: it has to be accessible directly (i.e.: without accessing any container object).
– One-at-a-time rule: the compiler will try to apply only one implicit at the time.
– Explicits-First rule: if the expression compiles as it is, no implicits will be applied.
– More-Specific-First rule: if there is more than one implicit conversion that could work, the one with the most restrictive type is chosen.
Implicits can be applied in three case scenarios only, for the sake of both the compiler and the poor developer that needs to understand what our code is doing.
Implicit conversion to an expected type
scala> case class Message(msg: String) defined class Message scala> implicit def intToMessage(n: Int) = Message(s"I am number $n") intToMessage: (n: Int)Message scala> val myMessage: Message = 1 myMessage: Message = Message(I am number 1)
Converting the receiver
scala> case class Message(msg: String) { | def talk() = println(msg) | } defined class Message scala> implicit def stringToMessage(text: String) = Message(text) stringToMessage: (text: String)Message scala> "hello".talk() hello
Implicit parameters
scala> implicit val defaultMsg = "hi dude" defaultMsg: String = hi dude scala> def talk(implicit msg: String) = println(msg) talk: (implicit msg: String)Unit scala> talk hi dude scala> talk("this is an explicit message!") this is an explicit message!