// stdlib가 제공하는 지연 초기화
val value by lazy { createValue() }
// stdlib가 제공하는 관찰자 패턴
var items: List<Item> by
Delegates.observablie(listOf()) { _, _, _ -> notifyDataSetChanged() }
// 프로퍼티가 사용될 때마다 로깅을 하는 위임 프로퍼티 구현 예
var token: String? by LoggingProperty(null)
private class LoggingProperty<T>(var value: T) {
operator fun getValue(thisRef: Any?, prop: KProperty<*>): T {
print("${prop.name} returned value $value")
return value
}
operator fun setValue(thisRef: Any?, prop: KProperty<*>, newValue: T): T {
val name = prop.name
print("$name changed from $value to $newValue")
value = newValue
}
val
는 getValue
를, var
는 getValue
와 setValue
연산이 필요하다.by
가 컴파일 되면 아래와 비슷한 형태가 된다.
getValue
, setValue
는 컨텍스트(this
)와 프로퍼티 레퍼런스도 함께 사용된다.getValue
, setValue
가 여러 개 있어도 컨텍스트를 활용하므로 상황에 따라 적절한 메서드가 선택된다.@JvmField
private val `token$delegate` =
LoggingProperty<String?>(null)
val token String?
get() = `token$delegate`.getValue(this, ::token)
set(value) {
`token$delegate`.setValue(this, ::token, value)
}
Map<String, *>
사용 예이다.inline operator fun <V, V1: V>Map<in String, V> // stdlib에 정의된 확장 함수
.getValue(thisRef: Any?, property: KProperty<*>): V1 =
getOrImplicitDefault(property.name) as V1
val map: Map<String, Any> = mapOf (
"name" to "Marcin",
)
val name by map
print(name) // Marcin
lazy
Delegates.observable
Delegates.vetoable
Delegates.notNull