Concise builder pattern in Kotlin using lambda’s with receiver

Joost Klitsie
3 min readJul 22, 2023

--

With the first stable version coming out in 2011, Kotlin has gradually been growing in terms of language features and adaptation. Kotlin is seen as a competitor for Java, but it is more than just “a better Java” as it is not just a JVM language; it can also compile to native as well as to Javascript. The language, as well as the compiler, are still undergoing rapid changes and its main competitor, Java, has even started to try and catch up to all the language features Kotlin has to offer. There are many language features that make it stand out and most people would mention null safety and how you can write clean and concise code with it compared to Java, but in this article, we will talk about other and perhaps more interesting features: Extension functions and lambdas with receiver.

As you guessed by the title, we will make a builder in Kotlin code. To make a comparison, first we can show shortly how a good old-fashioned builder would look like in Java:

Here you can see a simple Java class which can only be created by using the Builder

As you may guess, you can create a SimpleClass object by doing the following:

If you can imagine that we want to extend the functionality or use some helper methods, we must extend the functionality of the Builder class or write static helper methods. Also, if you construct a tree-like object, like HTML, you will have a nested hierarchy which your builder will reflect and constructing these kinds of objects in an old school builder pattern is quite a hassle.

In comes Kotlin, where we can use its language features to make writing these builders less complex, as well as the calling code, while making it highly extendable. As mentioned, we will be using extension functions and lambdas with receivers to achieve this. You may already know about these, in which case you can skip ahead, or continue reading here for a quick freshen up. Extension functions are a powerful way to extend functionality of your libraries and code. Kotlin itself heavily relies on extension functions to bring many features that many people take for granted and assume are just part of the language. As a matter of fact, the Kotlin standard library contains many functions that are often extension functions. Have you ever mapped a list from one type to the other? Trimmed a string? Used let, apply, run, also? Then you use extension functions and/or lambdas with receivers from the standard library. As the standard library is decoupled from Kotlin as a language, it is a very effective way to add functionality without having to change the language itself, unlike the case with Java. You can declare an extension function and call it in the following way:

Here you can see that within our extension function, we have a SimpleClass as the receiver object and we can access its fields and methods directly as within the function literal, SimpleClass is the explicit “this”. It does, however, consider visibility modifiers, which means we are not able to access private fields or private methods within SimpleClass, as extension functions do not modify the actual receiver class. This is logical, as “under the hood” extension functions are resolved statically and the JVM bytecode contains a static method where the SimpleClass is passed as an argument and the code within the function is invoked on the parameter. We can see this if we would compile the kotlin code into bytecode, and then decompile that into Java code, which is possible with Intellij Idea:

Similarly, lambdas with receiver also use a receiver object just as extension functions, but then in a lambda shape. This means that a lamba with receiver parameter must use a receiver object on which the lambda will be invoked. We can define this in similar fashion as extension functions. The following function declaration builds on our previous SimpleClass with Builder example:

When you call buildSimpleClass, you can pass a lambda which configures the builder we create within the function. After invoking the lambda on the builder object, the SimpleClass is build and returned. Now we can configure our SimpleClass like this:

Note here that in Kotlin we can take the last lambda argument out of the parentheses, and because there is only a single argument, we can omit them altogether. Now that we know all this, you can continue reading the next article, in which we will use the things we learned here to create a Kotlin DSL to generate HTML code!

https://medium.com/@joostklitsie/creating-a-simple-html-builder-in-kotlin-c4169c544f36

--

--

Joost Klitsie

I am developing Android Applications for over 10 years, with a passion for Kotlin, and won Best of Swiss Apps in 2023 with my team.