The concept of receivers was previously explained, so make sure you know what receiver is before reading further.

Both terms may seem a little bit unfamiliar, but you probably have been using receivers many times before. Many developers may not know the actual names, but they are definitely familiar with these concepts. Let’s dive straight into an examples.

val guitar = Guitar()

guitar.playTone()

In above example guitar is explicit receiver. There are however scenarios where we can access a member without specifying the receiver:

class Guitar {

fun playTone() { } fun playSong() {

playTone()

}

}

From within class, we can access members defined in this class simply by using member name (playTone method). Under the hood, receiver object (instance of the class) stores reference to those members. In above example, we are calling playTone method using an implicit receiver (we are accessing receiver implicitly without specifying receiver name). We can also explicitly refer to the receiver inside class and we will do so in below example by using this keyword:

class Guitar {

fun playTone() { } fun playSong() {

this.playTone() // explicit receiver

playTone() // implicit receiver

}

}

In our example receiver is the instance of the Guitar class in which methods are declared in. In this case, both of the calls are equivalent, but we’ve used an explicit receiver instead of implicit.

We say that receiver is explicit if we explicitly refer to an object when accessing its members.

We say that receiver is implicit if we don’t explicitly refer to object when accessing its members.

Typically we don’t use this as an explicit receiver because we don’t want to produce extra boilerplate. There are, however, few scenarios where explicit receivers are handy. The simplest example is accessing the field with the same name as a method parameter:

class Person() {

private var age: Int = 18 fun setName(age: Int) {

this.age = age

}

}

We have two variables with the same name (age field declared in class and age parameter defined in a method header). Variable without receiver always refers to the innermost enclosing scope (in this case method body). A field declaration is shadowed by method parameter declaration. Without using explicit receiver (this) we would not be able to access age field because another variable declaration with the same name exists in this scope (method parameter variable shadows a field).

We are also using an explicit receiver (super keyword) when we want to access method implemented in parent class instead of method overridden in the child class. Let’s consider this example where two interfaces define members with the same names and default implementations:

interface A {

fun doSomething() {

println("A is doing something")

}

} interface B {

fun doSomething() {

println("B is doing something")

}

} class Test : A, B {

override fun doSomething() {

doSomething() // infinitely recursive call

}

}

Notice that by default doSomething method defined in Test class would be called resulting in infinitely recursive call. To solve the problem we need to use explicit receiver (super) to tell the Kotlin compiler witch method we want to call. Both interfaces have default implementation of doSomething method, so we also need to qualify explicit receiver with interface name:

class Test : A, B {

override fun doSomething() {

super<A>.doSomething() // explicit receiver

super<B>.doSomething() // explicit receiver

}

}

Summing up. If one calls a method without explicitly naming a receiver object, we say that the receiver is implicit, otherwise we say that receiver is explicit.