Delegation over Inheritance
Delegation is built into the language using the by
keyword.
This seems a little bit similar to a Java dynamic proxy.
// an interface with two implementations
interface Itf {
fun something(): String
fun otherthing(): String
}
class SimpleImpl: Itf {
override fun something() = "simple something"
override fun otherthing() = "simple other thing"
}
class ComplexImpl: Itf {
override fun something() = "complex something"
override fun otherthing() = "complex other thing"
}
// Delegation - Caller is an instance of Itf
// which delegates to a target
class Caller(val target: Itf): Itf by target {
fun printTarget() = println("${target}")
// overridden version of otherthing - stops delegation call for this operation
override fun otherthing() = "local impl in Caller (hides ${target.otherthing()})"
}
// delegation - caller -> SimpleImpl
var caller = Caller(SimpleImpl())
println(caller.something()) // delegation - "simple something"
println(caller.otherthing()) // "local impl in Caller (hides simple other thing)"
caller.printTarget() // SimpleImpl@705ea294
// delegation - caller -> ComplexImpl
caller = Caller(ComplexImpl())
println(caller.something()) // delegation - "complex something"
caller.printTarget() // ComplexImpl@ef11f12
// chaining - caller -> caller -> ComplexImpl
caller = Caller(caller)
println(caller.something()) // delegation - "complex something"
caller.printTarget() // Caller@6939ce9c
Built-in Standard Delegates
Lazy
Properties
A property with lazy initialization. Should be created using the lazy()
function
// the expensive operation will not be called until the lazyInitialized variable is read/needed
// lazy takes a lambda function as argument
val lazyInitialized by lazy { expensiveOperation() }
By default lazy()
synchronizes the execution of the lambda function
observable
Properties
A property delegate that calls a callback function every time the property is changed
import kotlin.properties.Delegates.observable
// the observable function takes a lambda function that takes 3 arguments
var count by observable(0) { property, oldValue, newValue ->
println("Property: $property old: $oldValue: new: $newValue")
}
println("The value of count is: $count")
count++ // Property: var Line_359.count: kotlin.Int old: 0: new: 1
println("The value of count is: $count")
count-- // Property: var Line_359.count: kotlin.Int old: 1: new: 0
println("The value of count is: $count")
vetoable
Properties
Similar to observable
(called on all changes), but the lambda function should return a boolean value to potentially reject changes to a property