Search code examples
kotlindelegateslazy-initialization

How come Kotlin's built-in "lazy" function actually works?


I wanted to try something new with delegated properties in my Kotlin code. What I found in docs is that for custom delegated properties I need to create a class with obligatory methods - getValue and optionally setValue, which are part of interfaces mentioned in the docs:

You can create delegates as anonymous objects without creating new classes using the interfaces ReadOnlyProperty and ReadWriteProperty from the Kotlin standard library

I started digging through Kotlin's built-in delegate functions. I looked into implementation of lazy function which looks like following:

public actual fun <T> lazy(initializer: () -> T): Lazy<T> = SynchronizedLazyImpl(initializer)

And here's where my question stands: Why does it actually works? Lazy interface has only value property and some method determining its initialisation of the value. SynchronizedLazyImpl doesn't have much more than this. None of them have getValue or setValue methods, so why Kotlin doesn't complain and compiles successfully?


Solution

  • Looking at the source for Lazy here, you can see the following on line 37:

    /**
     * An extension to delegate a read-only property of type [T] to an instance of [Lazy].
     *
     * This extension allows to use instances of Lazy for property delegation:
     * `val property: String by lazy { initializer }`
     */
    @kotlin.internal.InlineOnly
    public inline operator fun <T> Lazy<T>.getValue(thisRef: Any?, property: KProperty<*>): T = value
    

    Essentially, there's a getValue extension function for Lazy instances that just returns the value property. SynchronizedLazyImpl just defines the value property, and getValue is automatically provided.