Welcome to the exciting world of Kotlin Delegation! In this lesson, we'll learn how to make our code cleaner and more efficient using Kotlin's Delegation feature. Let's dive in! š¤æ
In Kotlin, Delegation allows us to create an object that delegates some or all of its functionality to another object. This means we can reuse existing code and make our own code more concise.
š” Pro Tip: Delegation is a powerful tool for code reuse and organization in Kotlin.
Before we dive into Delegation, let's understand the difference between by-hand implementation and Delegation.
By-hand implementation means writing all the necessary code from scratch, while Delegation means using an existing object to handle some or all of the functionality.
Here's an example:
// By-hand implementation of a Stack
class MyStack {
private val items = mutableListOf<Int>()
fun push(item: Int) {
items.add(item)
}
fun pop(): Int? {
return if (items.isNotEmpty()) {
items.removeAt(items.lastIndex)
} else {
null
}
}
fun peek(): Int? {
return if (items.isNotEmpty()) {
items[items.lastIndex]
} else {
null
}
}
}Now, let's implement the same Stack using Delegation:
import kotlin.properties.Delegates
class DelegatedStack(val limit: Int = Int.MAX_VALUE) {
private val items = mutableListOf<Int>()
val size: Int by Delegates.observable(items.size) { _, old, new ->
if (new > limit) {
throw IllegalArgumentException("Stack size exceeded the limit.")
}
}
operator fun invoke(item: Int) {
if (size < limit) {
items += item
size++
} else {
throw IllegalArgumentException("Stack is full.")
}
}
operator fun invoke(index: Int): Int? {
if (index >= 0 && index < size) {
return items[index]
} else {
throw IndexOutOfBoundsException("Index out of bounds.")
}
}
operator fun invoke(index: Int, value: Int) {
if (index >= 0 && index < size) {
items[index] = value
} else {
throw IndexOutOfBoundsException("Index out of bounds.")
}
}
}In the DelegatedStack example, we use Kotlin's Delegates class to delegate the size, invoke, and set invoke operations to the underlying list. This makes our code cleaner and easier to maintain.
Kotlin provides several common delegation types:
ReadOnlyDelegate: Delegates read-only access to another property.ReadWriteDelegate: Delegates read-write access to another property.ObservableDelegate: Delegates read-write access and notifies observers when the value changes.RefDelegate: Delegates a reference to another property, allowing mutation.RefReadOnlyDelegate: Delegates a read-only reference to another property.Let's create an ObservableProperty example to understand Delegation better:
import kotlin.properties.Delegates
class ObservableInt(initialValue: Int = 0) {
var value by Delegates.observable(initialValue) { _, old, new ->
println("The value has changed from $old to $new")
}
}
fun main() {
val observableInt = ObservableInt(5)
println(observableInt.value)
observableInt.value = 10
println(observableInt.value)
}In this example, we create an ObservableInt class that uses Kotlin's Delegates.observable function to delegate the value property. When the value changes, it prints a message to the console.
What is Kotlin Delegation used for?
That's all for now! In the next lesson, we'll dive deeper into Kotlin Delegation and explore more examples. Keep learning, and happy coding! š