liveBook · Manning

Implicit receiver

As explained in Kotlin in Action, 2E

An implicit receiver is an object whose members are directly accessible within a callable body without an explicit object qualifier.

An implicit receiver is an object whose members can be called inside a callable body without an explicit qualifier. Kotlin gives a lambda with receiver a receiver type, making that object available as this. section 13.2.1

A StringBuilder becomes the receiver

fun buildString(builderAction: StringBuilder.() -> Unit): String { val sb = StringBuilder() sb.builderAction() return sb.toString() } val result = buildString { this.append("Hello, ") append("World!") } The lambda’s receiver is sb. Inside its body, this refers to that StringBuilder, so append("World!") needs no qualifier. section 13.2.1

The receiver can be explicit when clarity matters. apply and with invoke a receiver lambda on an object; apply returns the receiver, while with returns the lambda result. section 13.2.1

Implicit receivers support practical Kotlin DSL patterns:

  • HTML builders nest tag-specific receivers, allowing table, tr, and td calls to read like the structure they generate. section 13.2.2
  • Multiple nested receivers can make an unqualified property ambiguous; this@table and this@tr make the intended receiver explicit. section 13.2.2
  • @DslMarker restricts outer receivers with the same marker, preventing accidental access inside nested DSL blocks. section 13.2.2
  • Gradle-style dependency blocks use DependencyHandler as an implicit receiver, so implementation can be called directly. section 13.3.2
Listing 13.2 Redefining buildString to take a lambda with a receiver
fun buildString(
    builderAction: StringBuilder.() -> Unit   #1
): String {
    val sb = StringBuilder()
    sb.builderAction()                        #2
    return sb.toString()
}
 
fun main() {
    val s = buildString {
        this.append("Hello, ")                #3
        append("World!")                      #4
    }
    println(s)
    // Hello, World!
}

Compare an ordinary lambda taking StringBuilder explicitly with a lambda whose StringBuilder receiver makes member calls unqualified. section 13.2.1

How Kotlin in Action, 2E covers it

How deep it goes
Explains receiver types, this binding, apply and with, nested-scope hazards, and @DslMarker restrictions.
Examples
Demonstrates StringBuilder, HTML tables, nested tags, mutable maps, and Gradle-style dependency declarations.
What it assumes
Assumes familiarity with Kotlin lambdas and extension functions while defining receiver function types through concrete examples.
What you can do after
Build DSL-style APIs and control receiver visibility when nested lambdas make unqualified calls unclear.
How it connects
Connects lambdas with receivers to extension function types, apply, with, HTML builders, @DslMarker, and the invoke convention.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Kotlin in Action, 2E. The section links point to the parts of the book it draws on.