Image from https://softwareengineeringdaily.com/wp-content/uploads/2018/10/kotlin.jpg

How to Create and Use Kotlin Delegated Properties

Kenny Hadisaputra
4 min readJul 18, 2020

--

As a Kotlin developer, there’s a high chance that you have encounter code that looks like this

val aVariable by lazy { valueCreatorForThisVariable() }

The code by lazy is something that is exclusive to Kotlin. It is used to compute the value only once upon first variable accessed. This is known as “Delegated Properties” in Kotlin.

Delegated Properties as the name suggests, is properties in which the getter and setter is delegated to another class. So each time you get/set the value, you can do anything with that. From the accessor perspective, it is just treated as a simple variable.

How is it useful?

As I told you before, you can do anything with it anytime you get or set the value. For example, the Delegates.observable() delegate from Kotlin stdlib provides a way to track the old and new value, and do something with it each time a new value is set to that variable. More on this can be seen on this page.

How to make our own delegated properties

Kotlin provides a way to make our own delegates via interface. There are two interfaces that you can use, ReadOnlyProperty and ReadWriteProperty.

ReadOnlyProperty can only be used as a delegate to val variable whereas ReadWriteProperty can be used as a delegate to var variable.

ReadOnlyProperty

Let’s say we want to make a way for an int to always return random value every time we access that variable.

From the gist above, you can see that ReadOnlyProperty interface takes 2 generic type.

The first one is the class that can use this delegate. I use Any here as I want to be able to use this delegate everywhere. (If let’s say in Android, you want this class to only be accessible in Fragment , then put Fragment as the type)

The second one is the type of the variable. Since we want to make a variable that returns random int, I use Int as the second type.

Then, we have to implement a getValue method which will return the value we wanted. The method takes two parameters.

The first one is thisRef which type will match our first generic type. In this case, the type is Any . We can use this to get the instance of the class that contains this property.

The second one is property of type KProperty<*> . This can be used to get some metadata of the property. For example, you can know the name of the property.

For our case here, we just need to return Random.nextInt() to satisfy our requirement.

We can use our custom delegate by using by keyword and then followed by the instance of our delegate.

When this code runs, it will print

1st random: -487429269
2nd random: 1540701605

Just as we want, every time we access randomInt , it will return new random int.

ReadWriteProperty

ReadWriteProperty is practically the same as ReadOnlyProperty but since it can be used on var , we also need to handle the setter.

Let’s say we want to make a delegate which return an int which is the plus one of what we set. So, when we set 2 as the value, we want it to actually have 3 as the value.

The code above is pretty self explanatory. The getValue method works as a regular getter which return the value. The setValue will instead take the value we assigned and then add it by 1.

When we execute the code above, we set plusOne variable value to 10, but when printed, it will be

PlusOne is: 11

Usually, the delegate class is not used directly. Instead, we usually create an intermediary extension function to make it looked better and easier to use.

This is just an optional style and you can totally ignore this.

As an Android developer, I usually create some custom delegates to reduce boilerplate code. One of my favourite is a delegate that wrap ViewBinding in Fragment.

If you look at the official Android Documentation for using ViewBinding in Fragment here, it is pretty tedious. We have to create a nullable variable to store the binding because fragment’s view has different lifecycle than the fragment itself. So at some point, the binding could be invalid even though the fragment is still alive. And in the sample, they use backing field to hide the nullability when use, so we can access it without using ? symbol. We also have to make itu null on onDestroyView() method.

Luckily we can use Kotlin delegated properties to mitigate this boilerplate code to just a simple one line val property. Some people have already created posts on how to achieve this, so I think you can head over to their posts instead.

To conclude, I think as a developer who used to code in Java, when we migrate to Kotlin, we end up using Kotlin only up to how it is marketed to us (nullable type, extension function, etc). And because of that, we usually don’t use Kotlin up to its’ full potential.

There are so much features in Kotlin that we can use to leverage our productivity. One of them is Kotlin delegated properties and in this post, we can see that it can help us reduce much boilerplate code.

I really hope that we can start to use Kotlin more as a really powerful language rather than just being a better-than-Java language.

--

--

Kenny Hadisaputra

Android Developer and Kotlin Enthusiast (can also do a little bit iOS)