Running with Implicits – Extending Functionality


We had an interesting case of enhancing the functionality of a logging library with our own case to feed data into DataDog. That brought us back to the quick discussion on implicits in Scala.

Implicits in a quick sense is Magic! Too much of it and you get lost. In the right balance it is quite useful. One of the favorite examples that I use is from our Scala Training classes where we are working with functional objects. When we are working with functional objects we want all operations to take functional objects as well.

Let us assume that we are a Vulcan and we operate with VulcanMoney. Does that get your Star Trek adrenaline going 😉

class VulcanMoney(amount: Int) {
  val value = amount
  require(amount > 0)
  def add(that: VulcanMoney): VulcanMoney = new VulcanMoney(this.value + that.value)
  override def toString = "VM "+value
}

As you would notice, we have an add method which also takes a VulcanMoney. So essentially if we want to add some value to VulcanMoney, then we would have to add a VulcanMoney as well. Essentially, something like this would work

new VulcanMoney(10) add new VulcanMoney(20)     //> res3: Advanced.VulcanMoney = VM 30

but what if we need something like this to work?

new VulcanMoney(10) add 20 

The compiler needs some help to make this happen. In come the implicits. We define an implicit method which would convert the integer to VulcanMoney.

implicit def intToVulcanMoney(number:Int) = new VulcanMoney(number)
new VulcanMoney(10) add 20   //> res3: Advanced.VulcanMoney = VM 30

and boom our code works now! The only restriction being that this method definition should be in scope. What if you have 2 methods of the same kind i.e. f:(Int)=>VulcanMoney ? Simple the compiler would complain. Isn’t Scala strongly typed with a powerful compiler 🙂

With Scala 2.10 we got another goody where we could extend a class with something called an implicit class. An implicit class is a class marked with the implicit keyword. This keyword makes the class’ primary constructor available for implicit conversions when the class is in scope.

Let us assume that we want to add a decorate method to the existing String class. How do we do it?

implicit class DecoratedString(x: String) {
    def decorate: String = "~~" + x + "~~"
  }

Simple, we define an implicit class called DecoratedString which makes the primary constructor available for conversion to String. Now, we can call the shiny new “decorate” method on any string. Hence something like this would work

"Hello".decorate      //> res4: String = ~~Hello~~

Sweet!

Thus, either using implicit methods or classes we can easily extend the behavior with the help of the compiler.

Advertisements

About Vikas Hazrati

Vikas is the Founding Partner @ Knoldus which is a group of software industry veterans who have joined hands to add value to the art of software development. Knoldus does niche Reactive and Big Data product development on Scala, Spark and Functional Java. Knoldus has a strong focus on software craftsmanship which ensures high-quality software development. It partners with the best in the industry like Lightbend (Scala Ecosystem), Databricks (Spark Ecosystem), Confluent (Kafka) and Datastax (Cassandra). To know more, send a mail to hello@knoldus.com or visit www.knoldus.com
This entry was posted in Scala and tagged , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s