Implicit classes in Scala
Tags: scala, devjournal
Published: 2019-10-01 07:40:01

---
title: Implicit classes in Scala
published: true
description: 
tags: scala, devjournal
series: Learning Scala
---

In Scala there are two things (as far as I know) that can be declared with the `implicit` keyword: classes and function parameters. As the word implies, the keyword `implicit` signals the compiler to help you a bit so that you can avoid some clutter in your code.

# Implicit classes

With implicit classes we can add extra functionality to existing types in an easy and convenient way. Let's imagine that we want to extend the `String` class with a method that will prepend another string only if the first one is not empty.

```scala
implicit class ExtString(x: String) {
  def prependIfNotEmpty(prefix: String): String =
    if (x.isEmpty) x
    else prefix ++ x
}
```

And now we can assume that all instances of `String` in the scope have the method `prependIfNotEmpty`.

```scala
"type=unicorn&name=Twiligth Sparkle".prependIfNotEmpty("?") // "?type=unicorn&name=Twiligth Sparkle"
"".prependIfNotEmpty("Lorem ipsum") // ""
```

## Wait, isn't that monkey patching?

![Well yes, but actually no](https://thepracticaldev.s3.amazonaws.com/i/whv1w61006otej8bwiqr.jpg)

[Monkey patching](https://en.wikipedia.org/wiki/Monkey_patch) is a pattern used (and abused) in dynamic languages to override or add custom behaviour to existing types. To achieve a similar effect in Javascript, we could monkey patch the `String` prototype.

```javascript
String.prototype.prependIfNotEmpty = function (prefix) {
  return this.length > 0
    ? prefix + this.valueOf()
    : this.valueOf()
}
```

## So, what's the difference?

The difference is that in Javascript we are, in fact, modifying the original `String` prototype, which means that the change will affect the entire application. Thus, if we are using two modules or libraries that patch the same method in the same object with different behaviour, it's not going to work as we expect.

Scala is not actually touching the `String` type at all. When we add an implicit class, the compiler is going to expand our usages of `<string>.prependIfNotEmpty` to this:

```scala
new ExtString(<string>).prependIfNotEmpty(<prefix>)
```

And that's why our `ExtString` class receives a `String` argument, if you were wondering.

Moreover, the compiler will only use our `ExtString` if it is in scope, so we need to either declare it in the same scope where we are using it or import it, and a compile error will be thrown if there are two or more possible options with the same specificity to expand an implicit type in the same scope. So if we would declare a `ExtString2` class with the same method in the same scope, the compiler would complain that there are two options to expand `<string>.prependIfNotEmpty`. This makes unexpected behaviour issues due to type patching virtually impossible in Scala.

# Bonus: prependIfNotEmpty operator

Another cool thing about Scala is that you can use non-alphanumeric characters in method names, and that you can invoke a method with one argument with `object method argument` instead of `object.method(argument)`. Therefore, implementing operators for a type is as trivial as defining a method.

Instead of defining the method `prependIfNotEmpty`, we could create an operator for that. We can use the same notation as the prepend operator for arrays: `+:`, maybe throw in a question mark to signal that the operation will only happen if the string is not empty: `+?:`

```scala
implicit class ExtString(x: String) {
  def +?: (prefix: String): String =
    if (x.isEmpty) x
    else prefix ++ x
}

"?" +?: "123" // "?123"
"?" +?: ""     // ""
```

Note that in Scala operators that end with `:` associate to the right, which means that we write it in the form of `argument operator object` instead of `object operator argument`.

There are different opinions regarding whether adding operators is a good idea or not. It is not immediately obvious that `+?:` means _prepend only if the string is not empty_. I'm saying that you _can_ use custom operators, not that you _should_.