Which is the main problem you have as a developer when you use libraries that you don’t own? You can’t change them. If something is missing in the public API of a library, there is no chance to extend it. Using some excellent old object-oriented programming, you can overcome this problem by writing much boilerplate code. In the JVM ecosystem, modern programming languages, such as Scala, Kotlin or Groovy, try to give a solution to library extension, the Pimp My Library Pattern. Let’s go, and see what I am talking.
Let’s begin with a very extreme example. Imagine you want to add a method
Integer type in Java that allows you to translate an int into an instance of the
java.time.Period class. For whom that don’t know this class, a
Period represents a time, using days, months, years.
All that we want to achieve is having something like the following.
In more evolved languages, such as Scala or Kotlin, the above statement would look like the following.
In Java, you have no many such possibilities to achieve the goal. Since we cannot nor we want to modify directly the
Integer type, and we do not want to use inheritance on a concrete type, the only remaining possibility is to implement a method somewhere that receives in input an
Integer and returns a
Meh. We used a wrapper or some variance of the Object Adapter Pattern, but we are very far from the objective we originally had.
Let’s see how modern JVM languages, such as Kotlin, Scala and Groovy answer this problem.
Scala was the language that first introduced the Pimp My Library pattern. The pattern was introduced by the Scala language’s dad, Martin Odersky, in his article Pimp my Library, in the far 2006.
The pattern allows extending a type adding methods to it without using any form of inheritance. Using the pattern, we can add a method to the
Int type without extending from it.
The Scala language implements the pattern through implicit conversions. First of all, we need to declare an
implicit class that allows the compiler to convert our primary type into a new type that adds the method we want to have. In our case, the primary type is the
Inside the package
extension, or in any package, explicitly importing the package
extension, we can use the method defined in the type
ExtendedInt as a method defined for the
The tricks that make the magic are two:
- The declaration of the implicit type inside a package object forces the compiler to automatically import the
ExtendedInttype in all the files that belong from it.
- The class
ExtendedIntis declared as
- The class
ExtendedIntis a subclass of the type
AnyVal. From Scala 2.10, extending from
AnyValallows the compiler to perform some code optimisations. It’s called Custom Value Classes.
If I don’t interpret the result of the
javap command wrongly on the
.class files generated by the Scala compiler, Scala adopts a conversion to the bytecode of the implicit class similar to the wrapper approach I gave for Java.
int integer() is a getter of a private attribute and the constructor of the class takes as input a variable of type
int. The decompiled implicit Scala class has the same structure as the Java class
The standard library extensively uses the pattern. All the type defined with the suffix
Ops implement the pattern. Have a look at the
StringOps type for an example.
Dotty (Scala 3)
In the new version of Scala, Dotty or Scala 3, the possibility to extend a class with a new method becomes idiomatic. Extension methods are methods that have a parameter clause in front of the defined identifier.
You don’t need to use
implicit classes anymore. The resulting code is easier to understand than in the previous version of Scala.
Extension methods translate to methods where the leading parameter section is moved to after the defined identifier. So, the definition of days above translates to the plain method, and can also be invoked as such:
In Dotty, extension methods have a lot of other interesting properties that are beyond the scope of this post. If you are interested in them, please refer to Dotty documentation, Extension Methods.
Also, the newbie JVM-based language, Kotlin, has its implementation of the Pimp my library pattern. In Kotlin slang, the pattern implementation it’s called Extension functions. The pattern was introduced in the language to contrast the fact that the majority of the libraries a Kotlin developer could use are in Java, and not in Kotlin.
The syntax needed to declare an extension function is less verbose than the syntax used in the Scala language ( :O ).
In our example, the
Integer type is also called the receiver type. Whereas, the
this reference on the right of the assignment symbol is called the receiver object. The
this reference refers to the integer instance on which the extension method is called. To preserve encapsulation, you can access only to the public methods of the receiver object.
The compiler does not import the extension methods by default. As any other Kotlin entity, you need to import them before using explicitly.
Under the hood, the compiler translates every extension method in a
static method having the receiver object as its first parameter. The name of the enclosing class is equal to the name of the file that declares the extension function.
Suppose that we declared the
Integer.days function in a file called IntegerUtil.kt, then the Kotlin compiler compile our code into a static method inside a class called
It’s very similar to the solution we gave for the Java language.
The translation that the Kotlin compiler performs on extension functions allows us to call them also on nullable types. No method is called directly on the receiver object passed as the first parameter to a static method.
So, extension functions and the Kotlin type system allow us to declare something like the following.
You can safely use the above method in if-statements, to control if a nullable object contains a
null reference or not.
Awesome. Kotlin continues to surprise me every day.
Sometimes a library contains almost all that you need, but it lacks some feature that you desire. Extension using the regular object-oriented mechanisms is not a possibility in such cases. Many JVM-based languages give you the possibility to achieve the goal to add the methods you need to an existing library without modifying it.
The Pimp my library pattern is the mechanism to make the magic happen. Scala uses implicit objects and conventions to implement such a pattern. In contrast, Kotlin has a more natural approach that integrates very well with the Kotlin type system concerning the handling of null references.
Where are you Java? Will you ever join the party?
If you want, download the code of the Scala example from my repository on GitHub: pimp-my-library.