Implicit class

What is an Implicit class ?

Problem statement : How to add new functionality to existing classes whose source code you do not have ?

In Scala, an implicit class is a way to add methods to existing types without modifying them or using inheritance. It’s commonly used in conjunction with implicit conversions or enrichment of existing types.

Implicit classes are a powerful feature in Scala that allow you to add new methods to existing types without modifying their source code.

How to create an Implicit class ?

Implicit classes are used to extend or add methods to existing types. They’re defined using the implicit keyword before the class keyword. The class must have exactly one non-implicit constructor parameter, which becomes the type that is being extended.

  • An implicit class must be defined inside an object or a trait.
  • The class must have exactly one non-implicit constructor parameter, which becomes the type that is being extended.
  • Once declared, the implicit class enables automatic conversion to add methods to the class it extends.

One common use case is to extend the functionality of an existing class by adding new methods (e.g., adding utility methods to standard classes like String or Int).

Example

object ImplicitClassExample {
implicit class StringOps(val s: String) {
def removeVowels: String = s.replaceAll("[aeiouAEIOU]", "")
}

def main(args: Array[String]): String = {
val result = "Hello, World!".removeVowels
println(result) // Output: Hll, Wrld!
result
}
}

In this example:

  1. We define an implicit class StringOps that takes a String as its constructor parameter.
  2. We add a new method removeVowels to String.
  3. In the main method, we can now call removeVowels on any String as if it were a built-in method.

When you call "Hello, World!".removeVowels, Scala automatically wraps the String in a StringOps instance, allowing you to use the new method.

Another example :

object StringExtensions {
// Define an implicit class that extends String functionality
implicit class RichString(val str: String) extends AnyVal {
// Add a method to repeat a string
def repeat(n: Int): String = {
str * n
}
}
}

object Main extends App {
import StringExtensions._ // Import the implicit conversion

// Now we can call the `repeat` method on any String
val original = "Scala "
val repeated = original.repeat(3) // Scala Scala Scala

println(repeated) // Output: Scala Scala Scala
}
  1. implicit class RichString: This class wraps a String and adds a new method repeat.
  2. val str: String: This is the constructor parameter. It holds the value we are extending (i.e., the string).
  3. .repeat(n: Int): This new method allows us to repeat a string n times.
  4. import StringExtensions._: The implicit class must be in scope for the method to be available.
  5. When we call original.repeat(3), Scala automatically converts the String to RichString using the implicit class and invokes the repeat method.

Implicit classes are often used for:

  • Adding utility methods to existing types. Implicit class adds new methods to a type, improving the original API.
  • The conversion happens automatically when the method on the implicit class is called.
  • Must be defined inside an object or trait for scope control.