Kotlin this expression represents a reference to the current receiver object in your code. The this expression provides access to the instance of the class, object, or function that is currently being executed. In Kotlin, this expression can refer to different receivers depending on the context where it’s used.
The Kotlin this expression syntax is straightforward - you simply use the keyword this
followed by an optional label when disambiguation is needed. The this expression automatically resolves to the nearest enclosing receiver, making it intuitive for developers familiar with object-oriented programming.
In a basic class context, Kotlin this expression refers to the current instance of the class:
class Student {
private var name: String = ""
fun setName(name: String) {
this.name = name // this expression refers to current Student instance
}
fun getName(): String {
return this.name // this expression accesses instance property
}
}
In this example, this expression disambiguates between the parameter name
and the instance property name
. The Kotlin this expression ensures we’re assigning to the instance variable rather than the parameter.
Kotlin this expression is particularly useful in constructors when parameter names match property names:
class Book(private var title: String, private var author: String) {
fun updateBook(title: String, author: String) {
this.title = title // this expression refers to instance property
this.author = author // this expression avoids naming conflicts
}
fun getBookInfo(): String {
return "Book: ${this.title} by ${this.author}"
}
}
Here, this expression clarifies that we’re setting instance properties, not just reassigning parameters.
Kotlin this expression in extension functions refers to the receiver object being extended:
fun String.addExclamation(): String {
return this + "!" // this expression refers to the String being extended
}
fun List<Int>.getSum(): Int {
return this.sum() // this expression refers to the List receiver
}
In extension functions, this expression represents the object on which the extension function is called.
Kotlin this expression behaves differently across various scope functions:
class Person(var name: String, var age: Int)
fun demonstrateThisInScopeFunctions() {
val person = Person("Alice", 25)
// In 'run' scope function, this refers to the receiver
person.run {
this.name = "Bob" // this expression refers to person object
this.age = 30
println("Updated: ${this.name}")
}
// In 'with' scope function, this refers to the receiver
with(person) {
this.name = "Charlie" // this expression refers to person object
println("Name: ${this.name}")
}
}
Kotlin this expression in lambda expressions can refer to different receivers:
class Calculator {
fun calculate(operation: Calculator.() -> Int): Int {
return this.operation() // this expression refers to Calculator instance
}
fun add(a: Int, b: Int): Int = a + b
fun multiply(a: Int, b: Int): Int = a * b
}
fun useLambdaWithThis() {
val calc = Calculator()
val result = calc.calculate {
this.add(5, 3) * this.multiply(2, 4) // this expression refers to Calculator
}
}
Kotlin this expression can be qualified with labels to specify which receiver you’re referring to:
class Outer {
private val outerProperty = "Outer"
inner class Inner {
private val innerProperty = "Inner"
fun accessBothProperties() {
println(this.innerProperty) // this expression refers to Inner
println(this@Outer.outerProperty) // qualified this expression refers to Outer
}
fun demonstrateQualifiedThis() {
val lambda = {
println(this@Inner.innerProperty) // qualified this expression to Inner
println(this@Outer.outerProperty) // qualified this expression to Outer
}
lambda()
}
}
}
Qualified this expression uses the @
symbol followed by the class name to specify exactly which receiver you want to access.
Kotlin this expression in object declarations refers to the singleton instance:
object DatabaseManager {
private var isConnected = false
fun connect() {
this.isConnected = true // this expression refers to DatabaseManager object
println("${this::class.simpleName} connected")
}
fun disconnect() {
this.isConnected = false // this expression refers to singleton instance
}
fun getConnectionStatus(): Boolean {
return this.isConnected
}
}
Kotlin this expression within companion objects refers to the companion object instance:
class MathUtils {
companion object {
private const val PI = 3.14159
fun calculateCircleArea(radius: Double): Double {
return this.PI * radius * radius // this expression refers to companion object
}
fun getPI(): Double {
return this.PI // this expression accesses companion object property
}
}
}
Kotlin this expression in higher-order functions can have multiple receivers:
class StringBuilder {
private val content = mutableListOf<String>()
fun append(text: String): StringBuilder {
this.content.add(text) // this expression refers to StringBuilder instance
return this // this expression enables method chaining
}
fun build(): String {
return this.content.joinToString("")
}
}
fun buildString(builder: StringBuilder.() -> Unit): String {
val sb = StringBuilder()
sb.builder() // this expression within builder refers to StringBuilder
return sb.build()
}
Here’s a comprehensive example demonstrating various Kotlin this expression scenarios:
// Import statements
import kotlin.random.Random
// Main class demonstrating this expression
class GameCharacter(private var name: String, private var health: Int) {
// Companion object with this expression
companion object {
private const val MAX_HEALTH = 100
fun createRandomCharacter(): GameCharacter {
val randomName = "Player${Random.nextInt(1000)}"
return GameCharacter(randomName, this.MAX_HEALTH) // this refers to companion
}
}
// Method using this expression for property access
fun updateCharacter(name: String, health: Int): GameCharacter {
this.name = name // this expression disambiguates parameter from property
this.health = health // this expression refers to instance property
return this // this expression enables method chaining
}
// Method demonstrating this expression in scope functions
fun performActions() {
// Using this expression in 'run' scope function
this.run {
println("Character ${this.name} has ${this.health} health")
this.health -= 10 // this expression refers to current instance
}
// Using this expression in 'also' scope function
this.also { character ->
println("Processing character: ${character.name}")
// 'this' here still refers to the outer GameCharacter instance
this.health = maxOf(this.health, 0)
}
}
// Extension function demonstrating this expression
fun String.toCharacterName(): String {
return this.uppercase() // this expression refers to the String receiver
}
// Inner class demonstrating qualified this expression
inner class CharacterStats {
private val statsName = "Stats for ${this@GameCharacter.name}"
fun displayStats() {
println(this.statsName) // this expression refers to CharacterStats
println("Health: ${this@GameCharacter.health}") // qualified this expression
}
fun healCharacter(amount: Int) {
this@GameCharacter.health += amount // qualified this expression to outer class
println("${this@GameCharacter.name} healed for $amount points")
}
}
// Method creating inner class instance
fun getStats(): CharacterStats {
return this.CharacterStats() // this expression refers to current GameCharacter
}
// Method demonstrating this expression in lambda
fun executeWithContext(action: GameCharacter.() -> Unit) {
this.action() // this expression passes current instance as receiver
}
// Override toString using this expression
override fun toString(): String {
return "GameCharacter(name='${this.name}', health=${this.health})"
}
}
// Function demonstrating this expression usage
fun main() {
// Create character using companion object
val character = GameCharacter.createRandomCharacter()
println("Created: $character")
// Demonstrate method chaining with this expression
character.updateCharacter("Hero", 80)
.also { println("Updated: $it") }
// Demonstrate this expression in various contexts
character.performActions()
// Demonstrate qualified this expression with inner class
val stats = character.getStats()
stats.displayStats()
stats.healCharacter(15)
// Demonstrate this expression in lambda context
character.executeWithContext {
println("Executing action on ${this.toString()}") // this refers to GameCharacter
this.updateCharacter("Champion", 95)
}
println("Final character state: $character")
}
Expected Output:
Created: GameCharacter(name='Player123', health=100)
Updated: GameCharacter(name='Hero', health=80)
Character Hero has 70 health
Processing character: Hero
Stats for Hero
Health: 70
Hero healed for 15 points
Executing action on GameCharacter(name='Hero', health=70)
Final character state: GameCharacter(name='Champion', health=95)
This example demonstrates how Kotlin this expression works across different contexts including class methods, companion objects, scope functions, inner classes, and lambda expressions. The this expression provides clear references to the appropriate receiver object in each scenario, making your Kotlin code more readable and maintainable.