# Extension Functions

Suppose you discover a library that does everything you need … almost. If it only had one or two additional member functions, it would solve your problem perfectly.

But it’s not your code—either you don’t have access to the source code or you don’t control it. You’d have to repeat your modifications every time a new version came out.

Kotlin’s extension functions effectively add member functions to existing classes. The type you extend is called the receiver. To define an extension function, you precede the function name with the receiver type:

fun ReceiverType.extensionFunction() { ... }

This adds two extension functions to the String class:

// ExtensionFunctions/Quoting.kt
package extensionfunctions
import atomictest.eq

fun String.singleQuote() = "'$this'"
fun String.doubleQuote() = "\"$this\""

fun main() {
  "Hi".singleQuote() eq "'Hi'"
  "Hi".doubleQuote() eq "\"Hi\""
}

You call extension functions as if they were members of the class.

To use extensions from another package, you must import them:

// ExtensionFunctions/Quote.kt
package other
import atomictest.eq
import extensionfunctions.doubleQuote
import extensionfunctions.singleQuote

fun main() {
  "Single".singleQuote() eq "'Single'"
  "Double".doubleQuote() eq "\"Double\""
}

You can access member functions or other extensions using the this keyword. this can also be omitted in the same way it can be omitted inside a class, so you don’t need explicit qualification:

// ExtensionFunctions/StrangeQuote.kt
package extensionfunctions
import atomictest.eq

// Apply two sets of single quotes:
fun String.strangeQuote() =
  this.singleQuote().singleQuote()  // [1]

fun String.tooManyQuotes() =
  doubleQuote().doubleQuote()       // [2]

fun main() {
  "Hi".strangeQuote() eq "''Hi''"
  "Hi".tooManyQuotes() eq "\"\"Hi\"\""
}
  • [1] this refers to the String receiver.
  • [2] We omit the receiver object (this) of the first doubleQuote() function call.

Creating extensions to your own classes can sometimes produce simpler code:

// ExtensionFunctions/BookExtensions.kt
package extensionfunctions
import atomictest.eq

class Book(val title: String)

fun Book.categorize(category: String) =
  """title: "$title", category: $category"""

fun main() {
  Book("Dracula").categorize("Vampire") eq
    """title: "Dracula", category: Vampire"""
}

Inside categorize(), we access the title property without explicit qualification.

  • -

Note that extension functions can only access public elements of the type being extended. Thus, extensions can only perform the same actions as regular functions. You can rewrite Book.categorize(String) as categorize(Book, String). The only reason for using an extension function is the syntax, but this syntax sugar is powerful. To the calling code, extensions look the same as member functions, and IDEs show extensions when listing the functions that you can call for an object.

Exercises and solutions can be found at www.AtomicKotlin.com.