0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

関数を跨いだローカル変数の遅延初期化

Posted at

問題点

lazy関数でローカル変数を遅延初期化する場合、その変数を関数の引数として渡すと、
関数の呼び出し先でその変数を参照しなくても、関数を呼び出す時点で初期化が実行されてしまう。(LazyインスタンスのgetValueが呼ばれてしまう)

fun main() {
    val value: String by lazy {
        println("initialize value")
        computeValue()
    }

    (1..3).forEach {
        process(it, value)
    }
}

private fun process(index: Int, value: String) {
    println("index: $index")
    if (index % 2 == 0) {
        println("value: $value")
    }
}

private fun computeValue(): String {
    Thread.sleep(3000)
    return "Hello"
}

結果

initialize value
index: 1
index: 2
value: Hello
index: 3

解決策

lazyなプロパティを保持するクラスを作成し、関数の引数として渡す。

class LazyValueProvider<T>(initializer: () -> T) {
    val value: T by lazy {
        initializer()
    }
}

fun main() {
    val provider = LazyValueProvider {
        println("initialize value")
        computeValue()
    }

    (1..3).forEach {
        process(it, provider)
    }
}
}

private fun process(index: Int, provider: LazyValueProvider<String>) {
    println("index: $index")
    if (index % 2 == 0) {
        println("value: ${provider.value}")
    }
}

private fun computeValue(): String {
    Thread.sleep(3000)
    return "Hello"
}

結果

index: 1
index: 2
initialize value
value: Hello
index: 3
0
0
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?