Kotlin has delegated properties which is a very nice feature. But sometimes get()
and set()
methods are not enough. Let's say I want to create a Closeable
object lazily and to close it later. Here's an example of how such delegate property could be implemented:
fun <T : Closeable> closeableLazy(initializer: () -> T) =
CloseableLazyVal(initializer)
class CloseableLazyVal<T : Closeable>(
private val initializer: () -> T
) : ReadOnlyProperty<Any?, T> {
private var value: T? = null
override fun get(thisRef: Any?, desc: PropertyMetadata): T {
if (value == null) {
value = initializer()
}
return value
}
fun close() {
value?.close()
}
}
And that's how I would like to use it:
private val stream by closeableLazy { FileOutputStream("/path/to/file") }
fun writeBytes(bytes: ByteArray) {
stream.write(bytes)
}
override fun close() {
stream::delegate.close() // This line will not compile
}
Unfortunately, this approach doesn't work because it seems that Kotlin doesn't allow to access property delegates directly. Is there any way to do what I want? Or are there any plans to add such functionality to Kotlin because it would be such a neat feature.
Ok, so I came up with the following solution:
Notice, that the property's get method has a parameter
thisRef
. I require that it inherits fromCloseableDelegateHost
which will close any registeredCloseable
s when it is closed. To simplify the implementation I delegate this interface to a simple list-based implementation.UPDATE (copied from comments): I realized, you can just declare the delegate as a separate property and then delegate the second property to it. This way you can access the delegate itself easily.
In Kotlin 1.1 (since beta 2), delegates can be retrieved from properties, so you can now write