Kotlin Extension Functions

Kayvan Kaseb
Software Development
6 min readAug 17, 2022
The picture is provided by Unsplash

Nowadays, Kotlin has been considered as a modern statically typed programming language used by over 60% of professional Android developers, which helps you boost efficiency, satisfaction, and code safety. Furthermore, Kotlin has been recommended firmly by Google to build an Android app. One of the advanced features that Kotlin gives the programmer is the ability to add more functionalities to the existing classes, and you do not require to inherit them. This can be achieved through a feature, known as Extension Functions. This article will provide you with some main concepts and best-practices to use Kotlin extensions for Android developers.

Introduction and Overview

Essentially, an extension function is a member function of a class, which is defined outside the class. For instance, if you require to utilize a method to the String class that returns a new string with first and last character eliminated, you can be able to write an extension method for it. So, this method is not already available in String class. In general, extension functions have the potential to make your code more brief, readable, and logical by enhancing and removing boilerplate code from your project. Furthermore, less code means fewer opportunities for making errors. Eventually, there are some other benefits could be mentioned as follows:

  1. It can be able to add functionality to a final class. It means the class do not need to be defined as a non-final class.
  2. It can be able to add functionality without sub-classing, which means the object reference and the its implementation can be mentioned in your base class.
  3. It follows some best-practices in Object-Oriented programming, particularly Open–closed principle (in SOLID principles), which specifies entities, such as classes, modules, and functions should be opened for extension, but closed for modification.

Lastly, Kotlin is an expressive and concise programming language that decreases typical code errors, and integrates into existing Android applications easily. Moreover, Kotlin has been recommended firmly by Google to build an Android application. There are a number of reasons could be mentioned for using Kotlin in Android development. For instance, you can do more tasks in practice with less code. Google has mentioned that 67% of professional developers who use Kotlin mention Kotlin has increased their efficiency. One of the modern features that Kotlin gives the programmer is the ability to add more functionalities to the existing classes, and you do not need to inherit them. This can be achieved through an advanced feature, known as Extensions (Extension Functions). This essay will discuss some main concepts and best-practices to use Kotlin extensions in Android development.

Using Kotlin Extension Function

As noted, Kotlin offers the ability to extend a class or an interface with an advanced functionality without requiring to inherit from the class or using design patterns, like Decorator. This is performed with special declarations known extensions. In short, an extension function is a member function of a class, which is defined outside the class. For instance, you want to utilize a method to the String class that returns a new string with first and last character eliminated. This method is not already accessible in String class. Therefore, you can have an opportunity to use extension function in Kotlin programming to perform this task easily.

fun String.removeFirstLastChar(): String =  this.substring(1, this.length - 1)fun main(args: Array<String>) {
val sampleString= "Extension Function"
val output = sampleString.removeFirstLastChar()
println("The final string is: $output")
}

After running the code, you will see this as follows:

The final string is: xtension Functio

The this keyword inside an extension function refers to the receiver object. Also, the class name is called the receiver type.

The following example adds a swap function to the MutableList<Int>:

fun MutableList<Int>.swap(index1: Int, index2: Int) {
val tmp = this[index1]
this[index1] = this[index2]
this[index2] = tmp
}
fun main() {
val list = mutableListOf(2, 4, 6, 8, 10)
list.swap(1, 3)
println(list) // It will print [2, 8, 6, 4, 10]
}

Another example is that a new function is appended to the class using dot notation with class Circle.perimeter(), and its return type is Double.

class Circle (val radius: Double){
fun area(): Double{
return Math.PI * radius * radius;
}
}
fun Circle.perimeter(): Double{
return 2*Math.PI*radius;
}
fun main(){
val sampleCircle = Circle(2.5);
println("The area is: ${sampleCircle.area()}")
println("The Perimeter is: ${sampleCircle.perimeter()}")
}

Initially, extensions do not modify the classes they extend. After writing an extension, you cannot insert new members into a class. This means you can just only making new functions callable with the dot-notation on variables of this type.

The important point is that extensions are resolved statically. In other words, extension function is executed based on the type of the expression on which it is invoked fully. Thus, this is more significant the type resolved on the final execution of the expression at runtime. The following example prints Shape since the extension function called depends just only on the s parameter that is the Shape class.

open class Shape
class Square: Shape()
fun Shape.getName() = "Shape"
fun Rectangle.getName() = "Square"
fun printClassName(s: Shape) {
println(s.getName())
}
fun main(){
printClassName(Square())
}

Nullable Receiver

Extension functions can be defined with the class type that is nullable. In this situation, the check for null is added inside the extension function, and the appropriate value is returned. For example, you can see the output of the below code as follows:

class MyClass(val name: String) {
override fun toString(): String {
return "The Name is $name"
}
}
fun MyClass?.printResult() {
if (this == null) {
println("Null")

} else {
println(this.toString())
}
}

fun main() {

val sampleOutput = MyClass("Kotlin")
sampleOutput.printResult() //It will print The Name is Kotlin
null.printResult() //It will print Null
}

In addition, for instance, you can be able to call toString() in Kotlin without checking for null in practice because the check will occur inside the extension function as follows:

fun Any?.toString(): String {
if (this == null) return "null"

return toString()
}

Companion object extension functions

Initially, a companion object is an object that is mentioned inside a class and specified with the companion keyword. Companion object is used to call the member function of class directly by using the class name in similar way to static keyword in Java. If a class includes companion object, we can be able to define extension functions, as well as properties for the companion object.

class SampleClass {
companion object { }
}
fun SampleClass.Companion.printTest() { println("Test") }fun main() {
SampleClass.printTest()
}

Some significant points in Kotlin extensions

  1. If a class has a member function that has the same receiver type and the same name, it is also applicable to given arguments, the member always wins.
  2. It would be a proper solution for extension functions to overload member functions that have the same name and a different signature.
  3. In most situations, you define extension functions on the top level (under packages), however, for using an extension function outside its package, you should import it in a direct way.
  4. You can write extensions for one class inside another class. Hence, there are multiple implicit receivers can be existed in these extensions. So, members can be accessed without a qualifier.
  5. Extensions use the same visibility modifiers as regular functions. For instance, If an extension function is mentioned outside its receiver type, it cannot access the receiver’s private or protected members.

In conclusion

Recently, Google has mentioned that 67% of professional developers who use Kotlin mention Kotlin has increased their efficiency. One of the modern features that Kotlin gives the programmer is the ability to add more functionalities to the existing classes, and you do not need to inherit them. This would be achieved via special indication, which is called Extension Function. As a result, this capability could be effective for becoming code more cleaner and easy to read, and it could reduce the code as well. This essay discussed some main concepts and best-practices to use Kotlin extensions in Android development based on JetBrains documents and resources.

--

--

Kayvan Kaseb
Software Development

Senior Android Developer, Technical Writer, Researcher, Artist, Founder of PURE SOFTWARE YAZILIM LİMİTED ŞİRKETİ https://www.linkedin.com/in/kayvan-kaseb