Hanbit the Developer
Kotlin Documentation | Delegated properties 본문
Category: Concepts - Classes and objects
문서 링크: https://kotlinlang.org/docs/delegated-properties.html
Delegated properties
val/var <property name>: <Type> by <expression>
class Example {
var p: String by Delegate()
}
class Delegate {
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
return "$thisRef, thank you for delegating '${property.name}' to me!"
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
println("$value has been assigned to '${property.name}' in $thisRef.")
}
}
Standard delegates
Lazy properties
val lazyValue: String by lazy {
println("computed!")
"Hello"
}
fun main() {
println(lazyValue)
println(lazyValue)
}
computed!
Hello
Hello
특징:
- thread-safe
- 초기화와 사용하는 쓰레드가 언제가 같다면(싱글 쓰레드 환경), LazyThreadSafetyMode.NONE을 사용하여 오버헤드를 제거할 수 있다.
Observable properties
값을 할당할 때마다 블럭이 호출됨
class User {
var name: String by Delegates.observable("<no name>") {
prop, old, new ->
println("$old -> $new")
}
}
fun main() {
val user = User()
user.name = "first"
user.name = "second"
}
<no name> -> first
first -> second
vetoable(): 할당이 발생하기 전에 블럭 호출
Delegating to another property
var topLevelInt: Int = 0
class ClassWithDelegate(val anotherClassInt: Int)
class MyClass(var memberInt: Int, val anotherClassInstance: ClassWithDelegate) {
var delegatedToMember: Int by this::memberInt
var delegatedToTopLevel: Int by ::topLevelInt
val delegatedToAnotherClass: Int by anotherClassInstance::anotherClassInt
}
var MyClass.extDelegated: Int by ::topLevelInt
Storing properties in a map
class User(val map: Map<String, Any?>) {
val name: String by map
val age: Int by map
}
val user = User(mapOf(
"name" to "John Doe",
"age" to 25
))
MutableMap을 사용하여 read & write 모두 수행 가능
class MutableUser(val map: MutableMap<String, Any?>) {
var name: String by map
var age: Int by map
}
println(user.name) // Prints "John Doe"
println(user.age) // Prints 25
Local delegated properties
fun example(computeFoo: () -> Foo) {
val memoizedFoo by lazy(computeFoo)
if (someCondition && memoizedFoo.isValid()) {
memoizedFoo.doSomething()
}
}
Property delegate requirements
read-only 프로퍼티(val)에는 operator getValue() 함수를 제공해야 한다.
mutable 프로퍼티(var)에는 operator getValue(), setValue() 함수를 제공해야 한다:
class Resource
class Owner {
var varResource: Resource by ResourceDelegate()
}
class ResourceDelegate(private var resource: Resource = Resource()) {
operator fun getValue(thisRef: Owner, property: KProperty<*>): Resource {
return resource
}
operator fun setValue(thisRef: Owner, property: KProperty<*>, value: Any?) {
if (value is Resource) {
resource = value
}
}
}
delegate를 클래스를 작성하지 않고 anonymous object로 생성할 수 있다. 코틀린 standard library에서 제공하는 ReadOnlyProperty, ReadWriteProperty 인터페이스를 사용하면 된다:
fun resourceDelegate(resource: Resource = Resource()): ReadWriteProperty<Any?, Resource> =
object : ReadWriteProperty<Any?, Resource> {
var curValue = resource
override fun getValue(thisRef: Any?, property: KProperty<*>): Resource = curValue
override fun setValue(thisRef: Any?, property: KProperty<*>, value: Resource) {
curValue = value
}
}
val readOnlyResource: Resource by resourceDelegate() // ReadWriteProperty as val
var readWriteResource: Resource by resourceDelegate()
Translation rules for delegated properties
Providing a delegate
provideDelegate operator를 정의함으로써 객체 생성 로직을 확장할 수 있다:
class ResourceDelegate<T> : ReadOnlyProperty<MyUI, T> {
override fun getValue(thisRef: MyUI, property: KProperty<*>): T { ... }
}
class ResourceLoader<T>(id: ResourceID<T>) {
operator fun provideDelegate(
thisRef: MyUI,
prop: KProperty<*>
): ReadOnlyProperty<MyUI, T> {
checkProperty(thisRef, prop.name)
// create delegate
return ResourceDelegate()
}
private fun checkProperty(thisRef: MyUI, name: String) { ... }
}
class MyUI {
fun <T> bindResource(id: ResourceID<T>): ResourceLoader<T> { ... }
val image by bindResource(ResourceID.image_id)
val text by bindResource(ResourceID.text_id)
}
'Kotlin' 카테고리의 다른 글
Kotlin Documentation | Functions (0) | 2023.05.23 |
---|---|
Kotlin Documentation | Type aliases (0) | 2023.05.23 |
Kotlin Documentation | Delegation (0) | 2023.05.23 |
Kotlin Documentation | Object expressions and declarations (0) | 2023.05.23 |
Kotlin Documentation | Inline classes (0) | 2023.05.23 |