A Gentle Introduction to Delegation in Kotlin

Masoud Fallahpour
Dev Genius
Published in
4 min readJul 24, 2022

--

Photo by Saj Shafique on Unsplash

In object-oriented programming, delegation is an object-oriented design pattern that works as an alternative to inheritance. In delegation, an object handles a request by delegating it to another object. This other object, that does the real work, is called the delegate.

As delegation is a design pattern, it means that we can implement it in any object-oriented language. Some object-oriented languages like Kotlin support it natively meaning that there will be no boilerplate code.

An Example

Let’s go through a rudimentary example to get a basic idea about delegation. First, we define the Software interface.

Then we define two implementations for the interface we just defined.

Now we define a class called WordProcessor that implements the Software interface.

WordProcessor receives an instance of Software and when its getLicense is called, it simply delegates/forwards the call to software.

That’s it! Now you know what delegation is but there is more to it.

Class Delegation

The example you just saw is an example of class delegation. In class delegation class A delegates some or all of its responsibilities to class B.

As Kotlin supports class delegation natively, let’s implement the previous example in a more elegant way.

The above WordProcessor class has the exact same functionality as the one we defined previously but without any boilerplate code. The Kotlin compiler will generate the boilerplate for us!

We used the by keyword to let the Kotlin compiler do two things:

  1. Generating all the methods of the Software interface for WordProcessor.
  2. Delegating the calls of the generated methods to the corresponding methods of software.

Decompiling the bytecode of WordProcessor to Java, gives something like the following code.

The Kotlin compiler has done its job!

Now it’s time to talk about the other type of delegation which is called property delegation.

Property Delegation

Before talking about property delegation let’s see why we would need it.

An example

Consider the following class.

Imagine we want to implement the following logic for each property of User:

  • Print “<property name> is read” when reading the value of the property,
  • Print “<property name> is written” when assigning a value to the property.

So when running the following code:

We want to get the output below:

firstName is written
secondName is written
firstName is read
secondName is read

One naive approach is to manually add println statements when reading/writing any property of User.

The above code works but guess what. It’s not scalable at all and we are repeating the same logic. It would be ideal if we could define the logic once and use it without repeating the same logic over and over again. That’s where property delegates could help.

Defining a Property Delegate

A property delegate is nothing but a class that has very specificgetValue and setValue methods.

Let’s define a delegate that implements the same logic that we implemented earlier manually.

Note that for the following code to work we’ll need to add the following dependency to our build.gradle file (assuming we using Gradle of course!)

implementation("org.jetbrains.kotlin:kotlin-reflect:<insert version here>")

The getValue method is executed when we read the value of the property. It’s an operator method that must have the exact following parameters:

  • thisRef must be of type Any?. It’s the instance of the class which contains the delegated property. In case the delegated property is not defined in a class (like being defined in the main function) thisRef will be null.
  • property must be of type KProperty<*> or its subtypes. It’s the property itself.

The return type of getValue must be the same type as the property (or its subtype).

setValue is the method that gets executed when we assign a value to the property. It’s an operator method that must have the following parameters exactly.

  • thisRef has the exact same purpose as described above.
  • property has the exact same purpose as described above.
  • value is the value being assigned to the property.

Now we can use the delegate we just defined.

Running the above code generates the following output.

firstName is written
secondName is written
firstName is read
secondName is read

Here, again we’re using the by keyword for doing the property delegation. The by keyword tells the Kotlin compiler two things:

  1. When accessing the value of say firstName, instead of calling the default getter of firstName, call Delegate.getValue.
  2. When assigning a value to say firstName, instead of calling the default setter of firstName, call Delegate.setValue.

If we decompile the bytecode of User to Java, we will get the following code which confirms the fact that when setting/getting the value of firstName/lastName, it’s the Delegate that handles the job.

Note that the delegate we just implemented is a very simple and not-so-useful one. Just use your imagination and think about the things that we can achieve using property delegation.

--

--

Software engineering @ Klarna. Software engineer, *nix lover, curious learner, gym guy, casual gamer.