はじめに
公式の問題集「Kotlin Koans」を解きながらKotlinを学習します。
過去記事はこちら
- Introduction
- Classes
- Conventions
- Collections
- Properties
問題
独自のデリゲートを宣言することができます。EffectiveDate
クラスのメソッドを実装して、デリゲートできるようにします。timeInMillis
プロパティには、ミリ秒単位の時間のみを格納します。
MyDate.kt
で定義されている拡張関数MyDate.toMillis()
およびLong.toDate()
を使用します。
修正前コード.kt
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
class D {
var date: MyDate by EffectiveDate()
}
class EffectiveDate<R> : ReadWriteProperty<R, MyDate> {
var timeInMillis: Long? = null
override fun getValue(thisRef: R, property: KProperty<*>): MyDate {
TODO()
}
override fun setValue(thisRef: R, property: KProperty<*>, value: MyDate) {
TODO()
}
}
MyDate.kt
import java.util.Calendar
data class MyDate(val year: Int, val month: Int, val dayOfMonth: Int)
fun MyDate.toMillis(): Long {
val c = Calendar.getInstance()
c.set(year, month, dayOfMonth)
return c.getTimeInMillis()
}
fun Long.toDate(): MyDate {
val c = Calendar.getInstance()
c.setTimeInMillis(this)
return MyDate(c.get(Calendar.YEAR), c.get(Calendar.MONTH), c.get(Calendar.DATE))
}
問題のポイント
Local delegated properties
ローカル変数は、委譲されたプロパティとして宣言することができます。たとえば、ローカル変数を遅延させることができます。
fun example(computeFoo: () -> Foo) {
val memoizedFoo by lazy(computeFoo)
if (someCondition && memoizedFoo.isValid()) {
memoizedFoo.doSomething()
}
}
memoizedFoo
変数は、最初のアクセス時のみ計算されます。
もしsomeCondition
が失敗すれば、変数は計算されません。
解答例
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
class D {
var date: MyDate by EffectiveDate()
}
class EffectiveDate<R> : ReadWriteProperty<R, MyDate> {
var timeInMillis: Long? = null
override fun getValue(thisRef: R, property: KProperty<*>): MyDate {
return timeInMillis!!.toDate()
}
override fun setValue(thisRef: R, property: KProperty<*>, value: MyDate) {
timeInMillis = value.toMillis()
}
}