Kotlin - extension functions and properties

Kotlin, like as C#, provides the ability to extend a class with new functionality without having to inherit from the class or use any type of design pattern such as Decorator. This is done via special declarations called extensions. Kotlin supports extension functions and extension properties

Extension Functions

To declare an extension function, we need to prefix its name with a receiver type, i.e. the type being extended. The following adds a swap function to MutableList<Int>:

fun MutableList<Int>.swap(index1: Int, index2: Int) {
    val tmp = this[index1] // 'this' corresponds to the list
    this[index1] = this[index2]
    this[index2] = tmp

The this keyword inside an extension function corresponds to the receiver object (the one that is passed before the dot). Now, we can call such a function on any MutableList<Int>:

val list = mutableListOf(1, 2, 3)
list.swap(0, 2) // 'this' inside 'swap()' will hold the value of 'l'

Of course, this function makes sense for any MutableList<T>, and we can make it generic:

fun <T> MutableList<T>.swap(index1: Int, index2: Int) {
    val tmp = this[index1] // 'this' corresponds to the list
    this[index1] = this[index2]
    this[index2] = tmp

Kotlin declare the generic type parameter before the function name for make it to be available in the receiver type expression.

Extensions are resolved statically they do not actually modify classes which they extend. By defining an extension, you do not insert new members into a class, but merely make new functions callable with the dot-notation on instances of this class.

Nullable Receiver

Note that extensions can be defined with a nullable receiver type. Such extensions can be called on an object variable even if its value is null, and can check for this == null inside the body. This is what allows you to call toString() in Kotlin without checking for null - the check happens inside the extension function:

fun Any?.toString(): String {
    if (this == null) return "null"
    // after the null check, 'this' is autocast to a non-null type, so the toString() below
    // resolves to the member function of the Any class
    return toString()

Extension Properties

Similarly to functions, Kotlin supports extension properties:

val <T> List<T>.lastIndex: Int get() {
    return size - 1

Or in expression notation:

val <T> List<T>.lastIndex: Int get() = size - 1

Note that, since extensions do not actually insert members into classes, there's no efficient way for an extension property to have a backing field. This is why initializers are not allowed for extension properties. Their behavior can only be defined by explicitly providing getters/setters.


val Foo.bar = 1 // error: initializers are not allowed for extension properties

If you are interested of it, you can try it here online. Full documentation you can find here. All news can be founded in a Kotlin blog

Be awesome, use Kotlin!kotlin_250x250.png

All Rights Reserved

Let's register a Viblo Account to get more interesting posts.