skip to content

What is an extension function in Kotlin, and how do you declare one?

level: juniorimportance: must knowfreq 85%

answer

  1. Receiver type goes before the dot: fun Type.name()
  2. Inside the body, this = the receiver object
  3. Call with normal dot syntax, like a member
  4. Class is NOT modified — just convenient syntax
  5. Usually top-level + imported

basics

~20 s

An extension function lets you add a new function to an existing type without changing its source. You write the type name before the function name, like fun String.shout(), and call it as if it were a normal method.

solid answer

~40 s

An extension function adds behavior to a type you don't own (or can't modify) without inheritance or wrapping. You declare it by prefixing the function name with a receiver type: `fun String.shout(): String = this.uppercase() + "!"`. Inside the body, `this` refers to the receiver instance (the String here), and `this` can be omitted for member access. You call it with normal dot syntax: `"hi".shout()`. The class is not actually modified — the function is resolved statically. Extensions are commonly declared as top-level functions in a file and imported where needed. They are a core Kotlin idiom for building readable, fluent helper APIs (the standard library is full of them, e.g. `List.firstOrNull()`).

code

kotlin · 6 lines
kotlin
fun Int.isEven(): Boolean = this % 2 == 0

fun main() {
    println(4.isEven())  // true
    println(7.isEven())  // false
}

go deeper

for a junior

Can declare fun Type.name(), knows this is the receiver, and calls it with dot syntax.

for a middle

Explains it does not mutate the class and is a top-level, importable helper for readable APIs.

for a senior

Frames extensions as compile-time sugar with no runtime class modification and discusses visibility limits.

for a principal

Positions extensions in API design (fluent helpers vs members) and the trade-offs versus members for evolvable libraries.

## What an extension function is An **extension function** is a function declared *outside* a class but callable *as if* it were a member of that class. It lets you "add" a function to a type you cannot or do not want to modify — a JDK class, a library type, or even your own class — without subclassing, the Decorator pattern, or editing the original source. ## Declaring one The syntax puts the **receiver type** (the type being extended) before the function name, separated by a dot: ```kotlin fun String.shout(): String = this.uppercase() + "!" fun main() { println("hello".shout()) // HELLO! } ``` - `String` here is the **receiver type**. - The actual object the function is called on (`"hello"`) is the **receiver object**. - Inside the body, the keyword **`this`** refers to the receiver object. As with members, `this` is implicit, so `uppercase() + "!"` works without writing `this.`. ## Where you declare them Most extensions are **top-level** functions in a `.kt` file, so they can be imported anywhere: ```kotlin // in StringExtensions.kt package com.example.util fun String.shout() = uppercase() + "!" ``` Callers add `import com.example.util.shout`. You can also declare extensions inside a class or object, but top-level is the common, reusable form. ## Key mental model An extension does **not** modify the class and does **not** insert anything into the type's method table. It is pure syntactic convenience that the compiler resolves at compile time. This is why extensions are great for *helpers* (formatting, conversions, small computations) but cannot, for example, access `private` members of the receiver type.

  • Does an extension function actually add the method to the class?
    No. The class is untouched; the function is resolved at compile time. It only looks like a member at the call site.
  • Can an extension access private fields of the receiver type?
    No. It only sees the public (and, within the same file/module, internal) API of the receiver, because it lives outside the class.

Like a sticky note of helper instructions attached to an object — the object itself is unchanged, but anyone reading it can follow the extra notes.

saying these in an interview costs you the question

  • Claiming the extension modifies or reopens the original class
  • Saying it works via inheritance or runtime patching
  • Thinking extensions can read the receiver's private members
  • Not knowing 'this' refers to the receiver inside the body

context