skip to content

Inside an extension function body, what does `this` refer to, and how do you access the receiver explicitly?

level: juniorimportance: should knowfreq 55%

answer

  1. this = the receiver object
  2. Unqualified names resolve on the receiver first
  3. Explicit this to pass the whole object
  4. Labeled this@fnName to reach an outer receiver
  5. Same model powers apply/with/run and DSLs

basics

~20 s

Inside the body, this is the object the function was called on (the receiver). You can write this to refer to it, or just call its members directly without this, like in a normal method.

solid answer

~40 s

Within an extension function, `this` is the **receiver object** — the instance the function was invoked on. You can reference it explicitly (`this`, `this.length`) or implicitly: unqualified names resolve against the receiver first, so `length` means `this.length`. Explicit `this` is useful to disambiguate (e.g. to pass the whole receiver to another function, `process(this)`), or inside nested lambdas where a closer implicit receiver might shadow it — there you use a **labeled this**, like `this@shout`, to name the outer extension receiver. This implicit-receiver mechanism is exactly what powers Kotlin scope functions (`apply`, `with`, `run`) and type-safe builders/DSLs, which are themselves built on extension/lambda receivers.

code

kotlin · 9 lines
kotlin
fun String.tagWith(prefix: String): String =
    buildString {
        append(prefix)
        append(this@tagWith) // outer String receiver
    }

fun main() {
    println("core".tagWith("app-")) // app-core
}

go deeper

for a junior

Knows this is the receiver and that members can be called without writing this.

for a middle

Uses explicit this to pass the receiver and understands implicit-receiver resolution order.

for a senior

Handles nested receivers with labeled this@name and ties it to scope functions and DSLs.

for a principal

Designs DSLs that keep receiver scoping unambiguous, e.g. using @DslMarker to prevent accidental outer-receiver access.

## `this` is the receiver object When you declare `fun String.shout()`, the function has a **receiver** of type `String`. Inside the body, the keyword **`this`** refers to the specific object the function was called on: ```kotlin fun String.shout(): String { // this : String is the receiver object return this.uppercase() + "!" } ``` ## Implicit vs explicit receiver Just like inside a regular member function, `this` is **implicit**. Any unqualified name is first looked up on the receiver: ```kotlin fun String.firstChar(): Char = this[0] // or simply get(0) fun String.shout() = uppercase() + "!" // uppercase() == this.uppercase() ``` Write `this` explicitly when you need the whole object: ```kotlin fun String.logged(): String { println(this) // pass/print the receiver itself return this } ``` ## Labeled `this` for nested receivers When a lambda with its own receiver is nested inside the extension, the **innermost** `this` wins. To reach the outer extension receiver, use a **qualified/labeled this** named after the enclosing function: ```kotlin fun String.describe(): String = buildString { // here `this` is a StringBuilder append("len=") append([email protected]) // this@describe = the String receiver } ``` Here `this` alone is the `StringBuilder`; `this@describe` is the original `String`. ## Why this matters This implicit-receiver model is the foundation of Kotlin's **scope functions** (`with`, `run`, `apply` all expose a receiver as `this`) and **type-safe builders/DSLs** (each builder block has a receiver). Understanding labeled `this` is what lets you write and debug nested DSL code without ambiguity.

  • How do you reach the outer extension receiver from inside a nested receiver lambda?
    Use a labeled this, e.g. this@functionName, which names the enclosing extension's receiver.
  • Do you have to write `this` to call the receiver's members?
    No. this is implicit; unqualified member calls resolve against the receiver, just like in a normal member function.

Like the word 'here' spoken in a room: by default it means the room you're standing in, but you can say 'here in the lobby' to point to an outer room.

saying these in an interview costs you the question

  • Thinking this refers to the class containing the call site
  • Not knowing this can be omitted for member access
  • Being unable to disambiguate nested receivers with this@label
  • Confusing the receiver with a regular parameter

context