Implicits get a bad rep in Scala. The wisdom goes: “Implicits are great, unless someone else wrote them.” Their reputation is that of convenience at the cost of readability.

But I’m curious about their mysterious power so I thought I’d try a concrete example.

My last post about converting a Case Class to a Map is a perfect example of where implicits can shine.

Our end goal is to be able to call this method on any case class, and get a map:

myCaseClass.toMap

Implicits can be defined thru the implicit class keyword. There are some basic restrictions on implicit classes, so to adhere we can place our definition inside a util object.

Inside our object, we simply define our implicit class and its method(s). You’ll notice the syntax of the method is very similar to the def from the previous example

package com.lombardo.app.utils

import org.slf4j.LoggerFactory

object ApiUtils {

  implicit class ProductMapper(val obj: Product) {

    def toMap = {
      val keys = obj.getClass.getDeclaredFields.map(_.getName).toList
      val values = obj.productIterator.toList

      keys.zip(values).toMap
    }
  }
}

Now to use, we just import the utils object and call toMap on our case class instance directly. In this case, we are recording a ServerLog event using a repository service. Our repository service requires a Map as its input, and our implicit class makes the conversion from case class to map nice and clear:

import com.lombardo.app.utils.ApiUtils._

case class ServerEvent(userRequest: String, userAgent: String, elapsedTimeMs: Long)

class LoggerService {

  def logEvent(event: ServerEvent): Option[Int] = {

    repositoryService.insert(event.toMap)
  }
}