What is an extension function in Kotlin, and how do you declare one?
answer
- Receiver type goes before the dot: fun Type.name()
- Inside the body, this = the receiver object
- Call with normal dot syntax, like a member
- Class is NOT modified — just convenient syntax
- Usually top-level + imported
basics
~20 sAn 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 sAn 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 linesfun Int.isEven(): Boolean = this % 2 == 0
fun main() {
println(4.isEven()) // true
println(7.isEven()) // false
}go deeper
Can declare fun Type.name(), knows this is the receiver, and calls it with dot syntax.
Explains it does not mutate the class and is a top-level, importable helper for readable APIs.
Frames extensions as compile-time sugar with no runtime class modification and discusses visibility limits.
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