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.
So a delegate is just a class with two methods: for getting and setting value of a property. To give it some more information, it is provided with the property it's working with via the instance of KProperty class, and an object that has this property via thisRef . That's it!
Delegating to another propertyA property can delegate its getter and setter to another property. Such delegation is available for both top-level and class properties (member and extension). The delegate property can be: A top-level property. A member or an extension property of the same class.
Delegated apps are apps that receive additional capabilities from the profile owner or device owner apps. Some of these capabilities involve the framework calling into the apps. To receive these callbacks, delegated apps should subclass this class and override the appropriate methods here.
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)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With