DEV Community

loading...

Kotlin extension function vs function literal with receiver

frevib profile image Frevib ・2 min read

Kotlin extension function and function literal with receiver

In Kotlin it is possible to add a method (called member function in Kotlin) to an existing class. This is called an extension function.

It is also possible to access a member function from a class inside a function literal. This is called a function literal with receiver.

Extension function

Say you want to add a new member function to the StringBuilder class, e.g. appendMonkey() that appends the string “monkey” to a string. Because StringBuilder is in the Java SDK, we cannot modify it. In Kotlin we can define an extension function that extends an existing class like StringBuilder with a new member function.

We define the appendMonkey() extension function as follows:

fun StringBuilder.appendMonkey(): StringBuilder = this.append("monkey")

this refers to the StringBuilder object, and we can omit it:

fun StringBuilder.appendMonkey(): StringBuilder = append("monkey")

Full example:

import java.lang.StringBuilder

fun main() {
    val sb = StringBuilder()

    sb.append("Hello extension function ")
    sb.appendMonkey()

    println(sb.toString())
}

fun StringBuilder.appendMonkey(): StringBuilder = append("monkey")

Function literal with receiver

Closely related to the extension function is the function literal with receiver. There are two types of function literals:

  • lambda
  • anonymous function

In practice you will most likely use the lambda expression, so we use that in the example below.

Where with extension functions you can add a new member function to an existing class, with a function literal with receiver you can access the member functions of an existing class inside the lambda block (inside the curly braces {}).

Let's create a function literal with receiver that adds the string "monkey" to a string using the StringBuilder class.

val lambdaAppendMonkey: StringBuilder.() -> StringBuilder = { this.append("monkey") }

Again, this refers to the StringBuilder object, so we omit it:

val lambdaAppendMonkey: StringBuilder.() -> StringBuilder = { append("monkey") }

Full example:

 import java.lang.StringBuilder

fun main() {
    val lambdaAppendMonkey: StringBuilder.() -> StringBuilder = { append("monkey") }

    val sb = StringBuilder()
    sb.append("Hello lambda ")

    println(lambdaAppendMonkey(sb).toString())
}

Here, inside the block of the lambda we can access the append() member function because we explicitly stated the return type to be StringBuilder.() -> StringBuilder. This return type basically says:

"return a function that takes no arguments and returns a StringBuilder object, and give this function access to the StringBuilder member functions".

Good luck!

Discussion (0)

pic
Editor guide