Kotlin delegating to a future
java, kotlin
Solution
You can translate your Java code to Kotlin in a straightforward way using custom property getters:
class Example(fooId: Int) {
private val fooFuture = supplyAsync { httpClient.get(fooId) }
val foo: Foo
get() = fooFuture.get()
}
But Kotlin has a more powerful concept for generalizing property behavior -- the property delegates:
class Example {
val foo: Foo by someDelegate
}
In this example, `someDelegate` is an object that defines the behavior of property `foo`.
Though `Future<V>` cannot be used as a delegate out of the box in Kotlin, you can create your own property delegates by implementing `getValue(thisRef, property)` and (for mutable properties) `setValue(thisRef, property, value)` functions, thus explicitly providing the code to be executed when a property is read (and written, if mutable).
These functions can be either member functions for your project classes or extension functions, which fits the case with `Future<V>`. Basically, to use `Future<V>` as a property delegate, you have to define the `getValue(thisRef, value)` extension function for it, for example:
operator fun <V> Future<V>.getValue(thisRef: Any?, property: KProperty<*>) = get()
Here, the value the delegate will provide for a property will be simply taken from the `Future::get` call, but a proper implementation should probably take care of cancellation and exceptions handling. For this purpose, you can wrap a `Future<V>` into a class that will also define the fallback values/strategies, and then use this class' objects in `by`.
Then you can use `Future<V>` objects as delegates for your properties:
class Example(fooId: Int) {
val foo: Foo by supplyAsync { Thread.sleep(2000); fooId }
}
fun main(args: Array<String>) {
val e = Example(123)
println(e.foo)
}
Problem
I am trying to learn Kotlin and delegates are both interesting and confusing. I have a situation where, in a java class I would take a constructor arg, create a Future (the ID represents a resource in another system) and stash the Future as an instange variable. Then the "getXXX" would call `Future.get()` Here is a sample java class ``` public class Example { private Future<Foo> foo; public Example(String fooId) { this.foo = supplyAsync(() -> httpClient.get(fooId)); } public Foo getFoo() { return foo.get(); } } ``` I am not supplying the Kotlin example because I am simply not sure how to construct it.