Kotlin: Having Fun with Delegation

Created:

Kotlin, a new powerful JVM language, offers two types of delegation: property delegation and interface delegation. Inspired by a StackOverflow question I came up with a small solution for lazy closeable properties that demonstrates both of these features.

The Problem

The author of the question wanted to implement properties of type Closeable that are lazily initialized and automatically closed if the containing class is closed.

The solution

First we define the implementation for the property delegate CloseableLazyVal:

class CloseableLazyVal<T : Closeable>(
        private val initializer: () -> T
) : ReadOnlyProperty<CloseableDelegateHost, T> {

    private var mValue: T? = null

    override fun get(thisRef: CloseableDelegateHost, desc: PropertyMetadata): T {
        var value = mValue

        if (value == null) {
            value = initializer()
            thisRef.registerCloseable(value)
        }

        return value
    }

}

fun <T : Closeable> closeableLazy(initializer: () -> T) = CloseableLazyVal(initializer)

If you're not familiar with property delegates, they are ordinary classes that encapsulate functionality that you would usually put in your getters (and optionally setters). Implementing the interface ReadOnlyProperty is optional but helps to get the method signatures right. In this case our delegate lazily initializes a Closeable using the constructor parameter initializer and simply returns it. closeableLazy is just a factory method.

The interesting part is the parameter thisRef. It's a reference to the enclosing class where the property is declared. We require that it implements the interface CloseableDelegateHost which we will discuss next. When the Closeable is instantiated, it is registered with the host which is responsible for closing it.

The definition for CloseableDelegateHost is straightforward. It inherits from Closeable and declares one additional method:

interface CloseableDelegateHost : Closeable {
    fun registerCloseable(prop: Closeable)
}

Because we don't want to repeat ourselves everytime we want to use one of our new properties, we implement it once and reuse it where possible:

class ClosableDelegateHostImpl : CloseableDelegateHost {

    val closeables = arrayListOf<Closeable>()

    override fun registerCloseable(prop: Closeable) {
        closeables.add(prop)
    }

    override fun close() = closeables.forEach { it.close() }
}

The remaing question is how to reuse the class. In Java the answer would be "by inheriting from it". In Kotlin one favors composition over inheritence by delegating interface implementations like so:

class Foo : CloseableDelegateHost by ClosableDelegateHostImpl() {

    fun writeBytes(bytes: ByteArray) {
        stream.write(bytes)
    }

    private val stream by closeableLazy { FileOutputStream("/path/to/file") }
}

Our class implements the interface CloseableDelegateHost but doesn't inherit from ClosableDelegateHostImpl, instead it delegates the implementation to it. This allows us to inherit from other classes if necessary.

As a bonus, we have perfect type safety because this code wouldn't compile if Foo didn't implement CloseableDelegateHost.

If you like, you can try out a modified version of this code here.