코틀린은 코드 재사용과 관련해 프로퍼티 위임이라는 새로운 기능을 제공한다.
프로퍼티 위임을 사용하면 일반적인 프로퍼티의 행위를 추출해 재사용할 수 있다.
lazy를 이용해 지연 프로퍼티를 사용하면 생성과 동시에 값을 초기화 할 수 있다.
val value by lazy { createValue() }
fun createValue(): String = "Test"
프로퍼티 위임을 사용해 observable 패턴도 쉽게 만들 수 있다.
var items: List<Item> by
Delegates.observable(listOf()) { _, _, _ ->
notifyDataSetChanged()
}
var key: String? by
Delegates.observable(null) { _, old, new ->
Log.e("Key changed from $old to $new")
}
간단한 프로퍼티 델리게이트를 살펴보자.
// AS-IS 델리게이트 적용 전
var token: String? = null
get() {
print("token returned value $field")
return field
}
set(value) {
print("token changed from $field to $value")
field = value
}
var attempts: Int = 0
get() {
print("attempts returned value $field")
return field
}
set(value) {
print("attempts changed from $field to $value")
field = value
}
위 두 token, attempts는 타입은 다르지만 거의 같은 처리를 하며 프로젝트 내에서 자주 반복되어 사용될 만한 패턴이다. 따라서 프로퍼티 위임을 활용해 추출할 수 있다.
// TO-BE 델리게이트 적용 후
var token: String? by LoggingProperty(null)
var attempts: Int by LoggingProperty(0)
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
) {
val name = prop.name
print("changed from $value to $newValue")
value = newValue
}
}
프로퍼티 위임이 어떻게 동작하는지 이해하려면 by가 어떻게 컴파일되는지 살펴보자
@JvmField
private val 'token$delegate' = LoggingProperty<String?>(null)
var token: String?
get() = 'token$delegate'.getValue(this, ::token)
set(value) { 'token$delegate'.setValue(this, ::token, value) }
멤버 함수 뿐만 아니라 확장 함수로도 만들 수 있다.
val map: Map<String, Any> = mapOf(
"name" to "Marcin",
"kotlinProgrammer" to true
)
val name by map
inline operator fun <V, V1 : V> Map<in String, V>
.getvalue(thisRef: Any?, property: KProperty<*>): V1 =
getOrImplicitDefault(property.name) as V1
코틀린 stdlib의 아래 프로퍼티 델리게이터를 알아 두면 유용하게 활용할 수 있다.
- lazy
- Delegates.observable
- Delegates.vetoable
- Delegates.notNull
정리
프로퍼티 델리게이트는 프로퍼티와 관련된 다양한 조작을 할 수 있다. 표준 라이브러리의 lazy와 observable이 대표적인 예이다.
Reference
- 이펙티브 코틀린 - 프로그래밍 인사이트, 마르친 모스칼라 지음, 윤인성 옮김
개인적인 기록을 위해 작성된 글이라 잘못된 내용이 있을 수 있습니다.
오류가 있다면 댓글을 남겨주세요.