Implicit classes

So far, we have discussed implicit conversions and the extension methods pattern. The implementation is usually done in such a way that the old type is wrapped in an instance of a new type, which then provides the additional methods. We looked at StringOps as an example, but let's try to come up with a homegrown implementation of this pattern. We'll have a type, A, and we want it to be able to do some operation, b:

case class A[T](a: T) { def doA(): T = a }
A("I'm an A").doB() // does not compile

We can fix the compile error by defining a class, with the required operation, and by providing an implicit conversion from A to B:

case class B[T](b: T) { def doB(): T = b }

import scala.language.implicitConversions
implicit def a2b[T](a: A[T]): B[T] = B(a.a)

A("I'm an A").doB() // works

This approach is so common that Scala has a special syntax for that called implicit classes. It combines defining a class and an implicit conversion into one definition of the class. The extended type becomes an argument for the constructor of the new class just as, in the previous code and in the following example:

implicit class C[T](a: A[T]) { def doC(): T = a.a }
A("I'm an A").doC()

It's cleaner and it does not require a scala.language.implicitConversions import. 

The reason for this is that there is a subtle but significant difference between plain implicit conversions and implicit classes. While an implicit conversion can represent any kind of change, including already existing and/or primitive types, an implicit class is something that is created with the typed conversion in mind. The fact that it accepts the initial type as a constructor parameter makes it parameterized by this type—in a sense. All in all, it is safer to use implicit classes than implicit conversions.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.148.113.229