Extension Functions in Kotlin

Sena Zincircioğlu
5 min readDec 9, 2022

--

Kotlin

Hello everyone,

In this article, we will talk about the concept of Extension, Extension Functions in Kotlin and the properties of these.

Extensions and Extension Function

Extending a class without having to inherit from the class or use design patterns is called “Extensions” in Kotlin. In other words, thanks to Extensions in Kotlin, we can add another classes functionality to our existing class without inherit them. The functions we define to provide this are also called Extension Functions.

Extension functions are declared like any other functions in Kotlin. The only difference is that it is created by adding the “receiver type”, which represents the expanded type, to the beginning of the function name.

Example

Suppose that we have a Mutable list of Integers.

If we want to write a function that takes the indexes of two elements in this list and returns the sum of those elements, we can write a function as follows.

Thus, when we want to get the sum of the elements with index 0 and 2 in the list, we can call this function as follows.

As a result, we have extended the “sum” function with the receiver type “MutableList<Int> “. So we can say that “sum” is defined as an Extension function.

Properties of Extension Functions

  1. One thing to note about Extension Functions is that they are resolved statically. So according to the receiver type, they are not virtual. In other words, which Extension Function is executed depends entirely on the type of expression in which it is called, rather than the type that is parsed at the last execution of the expression at runtime.

In the example above you can notice that class B inherits class A and the argument passed to displayClassName() is an instance of class B. In such a case, it can be thought that the output should be “B” based on the object-oriented programming concept of dynamic method dispatch. However, because Extension functions are statically resolved, getName() is called in type A. Hence the output:

2. If a class has a member function which has the same name and same arguments with an Extension function getting that class as receiver type, the member function will run instead of Extension function when the function is calle.

In this case the output will be “This is Member Function”.

But in the same situation, if the Extension function overloads the member function with a different signature, the Extension function will run when the same function is called in accordance with Extension function’s signature.

In this case the output will be:

3. Extension functions can be defined with nullable receiver type, and we can call such functions with objects with null values. In such a case, we can check null cases inside the function.

4. Kotlin allows to define Extensions very similar to how we define Extension function.

There is no efficient way for an extension to have a backing-field, since the extensions don’t actually add members to classes. Therefore, initializers are not allowed for extensions. Their behavior can only be defined by explicitly providing getter/setter.

5. Kotlin also allows to define extension function for classes with companion object.

6. An extension function created for one class can be defined inside another class. The instance of the class that contains such extension functions is called “Dispatch Receiver”, and the instance of the class that creates the receiver type of the function is called “Extension Receiver”.

Such extension functions are inaccessible outside the class in which they are defined. If you try to access such functions from outside the class, you will get an error. Considering this situation, we can give the following piece of code as an example of correct usage.

In case of a name conflict between members of a dispatch receiver and an extension receiver, the extension receiver takes precedence. You can use the qualified this syntax to reach members of the dispatch receiver.

7. We can also define such extension functions as “open” or “override” within the subclass. This means that the dispatch of these functions is virtual according to the dispatch receiver type and static according to the extension receiver type.

Note

Extensions use the same access modifiers(private, protected, and public) as regular functions declared in the same scope. For example:

* An Extension declared at the top level of a file can access other “private” top-level units in the same file.

* If an extension function is declared outside of the receiver type class, it cannot access the private or protected members of the receiver.

Conclusion

  • Adding the properties of another class to our existing class in Kotlin without performing any inheritance is called “Extension”, and the functions we define to provide the Extension are called “Extension Functions”.
  • Extension functions are resolved statically and the member functions of the receiver type class with the same name as the Extension Function take precedence over this Extension Function
  • Extension Function can be defined with nullable receiver type.
  • Extension Functions can also be defined inside a different class than the class that is the receiver type of it.
  • Extensions have the same access modifiers as regular functions declared in the same scope.

--

--