Receivers in Function Types

Earlier in the book, we saw the apply() scope function:

class SomethingOrAnother {
  var someProperty = 123
}

val foo = SomethingOrAnother().apply {
  someProperty = 456
}

In the lambda expression that we pass to apply(), the value of this is whatever we call apply() upon. with() works similarly, except that this is whatever we pass as the parameter to with():

class SomethingOrAnother {
  var someProperty = 123
}

fun main() {
  val foo = SomethingOrAnother()

  with(foo) {
    someProperty = 456
  }
}

You might think that this is some sort of compiler magic. In a sense, perhaps it is. However, both apply() and with() are functions implemented in Kotlin itself, and you can use this approach to tailor this in some context of your own.

What with() Looks Like

with() is a very simple inline function:

public inline fun <T, R> with(receiver: T, block: T.() -> R): R {
    return receiver.block()
}

It takes two parameters, receiver and block. receiver is just an ordinary parameter, albeit one declared using a generic type T. block is where the fun lies.

with() uses two generic types: T and R. T is the type for the receiver parameter, and R is what with() returns.

block is declared as T.() -> R. () -> R is a declaration of a function type. T.() -> R is a declaration of an extension function type, where we need to associate any call of that function type with something of type T.

with() invokes block via receiver.block(). The combination of T.() -> R syntax and receiver.block() says that this, in the context of the invoked block, is receiver.

If we go back to the with() example from earlier in this chapter:

class SomethingOrAnother {
  var someProperty = 123
}

fun main() {
  val foo = SomethingOrAnother()

  with(foo) {
    someProperty = 456
  }
}

receiver in this case is our SomethingOrAnother instance (foo). block is our lambda expresion ({ someProperty = 456 }). Given how with() is implemented, this in that lambda expression is the SomethingOrAnother instance, which is why we can manipulate someProperty without specifying that object directly.


Prev Table of Contents Next

This book is licensed under the Creative Commons Attribution-ShareAlike 4.0 International license.