How by Lazy Works

Implement a simpler version of by lazy

Guowei

2 minute read

by lazy is implemented by using the “property delegation” in Kotlin. But if you look into the source code and trying to understand what is going on, it can be confusing, because it is full of locks and generics and where’s the getValue()` function they say that the delegation must implement??

In the handmade spirit (best way to learn is by doing it yourself), let’s do a stripped down version ourselves.

First, let’s wriite a MyLazy interface.

interface MyLazy {
    val value: Int
}

This is not really necessary, since we are not going to have multiple implementations of Lazy, but since there is interface Lazy in kotlin, let’s just add one too.

Next, let’s add the required getValue() function, by using an extention function. This is where I get stuck when reading the original implementation in kotlin. This also reveals one biggest downside of extentiion functions, poor code discoverability.

operator fun MyLazy.getValue(thisRef: Any?, property: KProperty<*>) = value
Then let’s add MyLazyImpl to implement MyLazy interface.
object UNINITIALISED
class MyLazyImpl(val initializer: () -> Int) : MyLazy {
    private var _value: Any = UNINITIALISED
    override val value: Int
        get() {
            if (_value == UNINITIALISED) {
                _value = initializer()
            }
            return _value as Int
        }
}

Finally, let’s add this helper function.

fun myLazy(initializer: () -> Int): MyLazy = MyLazyImpl(initializer)

And now we are done!

comments powered by Disqus