Idiomatic Kotlin: Extension functions

Tompee Balauag
Familiar Android
Published in
4 min readJul 5, 2018
Photo by Anthony Intraversato on Unsplash

This new series is about how to use Kotlin efficiently and learning some of the underrated features of Kotlin. All the articles can be found at the end.

In this article, we will talk about extension functions and its interoperability with Java. Let’s get started.

What is an extension function?

An extension function is function that can be “added” to an existing type without needing to derive a class from it. It can be called as a member of the class even though it is defined outside of it. It is not a new concept as some popular programming languages like C# and Swift already support it.

Motivation

One of the motivations of extension functions is seemless integration with legacy code. Imagine if you can extend a class from your third-party library without actually inheriting it, and not breaking encapsulation at the same time, you can eliminate much of the boilerplate code and unnecessary derived classes.

How can I define an extension function?

Let us take a look at an example and work our way from there.

This is a convenience function to get the second character of a string if it is available. Now let us analyze the syntax. The String right after the fun keyword is called the receiver type. This is the type that you want to extend. The function name follows the type after a .. Now, the receiver object can be referenced inside the function using this. The this is implicit. You can omit it when calling the object methods and properties inside the extension function body. Note that you can only call public methods and properties of the receiver object. This is what keeps encapsulation intact. The reason why will be discussed later.

Referencing extension functions

Extensions, like any other functions, need to be imported (or in the same package) to be able to use. If for example the above code is added in `extensions` package, you have to import it like

import extensions.second

And use it like

val string = "12"
print(string.second())

Extension function under the hood

Let’s take a look at the decompiled version of our function above.

Under the hood, our extension function is actually a static function with the first parameter as the receiver object. It is enclosed in a class with name generated as the filename appended with kt (in my case, the filename is ExtensionFunctions). Knowing that it is converted as a static function, it doesn’t add any overhead in terms of performance. And it also explains why we can only access public methods and properties of the receiver object.

Referencing an extension function from Java can therefore be possible. You just have to know the filename and the method name. In our case it can be invoked by

char second = ExtenstionFunctionsKt.second(12);

Inheritance and Polymorphism

Extension methods are not inherited and cannot be overriden. Let’s take a look at why.

Consider two classes with one class inheriting the other one.

If we instantiate a Derived object and assign it to a Base variable and print getString, we will get Derived, which is expected as the method is resolved in runtime. What happens if we throw extension function to the mix?

That’s right, the classes and their relationship will be unaffected. This is because extension functions are static methods outside of the class. To help us visualize more, let us define an extension function for both classes.

The decompiled code for the above extension functions would be

They are static methods and are resolved at compile time. Therefore, calling them via super will not work (let alone compile). Overriding is just not possible as Kotlin resolves them statically.

Bonus: Extension Properties

Extending properties is also a thing. However, they do not really extend the fields of Java objects. In fact, extension objects don’t even have a backing field at all. That is why it is mandatory for you to implement at least a getter. Let’s modify our function as a property instead.

Calling this function is straightforward, just use property access syntax. In java, it is converted to a getter function like this:

ExtensionFunctionsKt.getSecond("12");

That’s it for extension functions and properties. This idiomatic Kotlin series will be updated with more topics so always stay tuned.

Check out the other articles in the idiomatic kotlin series. The sample source code for each article can be found here in Github.

  1. Extension Functions
  2. Sealed Classes
  3. Infix Functions
  4. Class Delegation
  5. Local functions
  6. Object and Singleton
  7. Sequences
  8. Lambdas and SAM constructors
  9. Lambdas with Receiver and DSL
  10. Elvis operator
  11. Property Delegates and Lazy
  12. Higher-order functions and Function Types
  13. Inline functions
  14. Lambdas and Control Flows
  15. Reified Parameters
  16. Noinline and Crossinline
  17. Variance
  18. Annotations and Reflection
  19. Annotation Processor and Code Generation

--

--