14

In the example below, t::x returns a reference to a property getter. How do I obtain the same for a setter?

class Test(var x: String) {}

fun main(args: Array<String>) {
    val t = Test("A")

    val getter: () -> String = t::x
    println(getter()) // prints A

    val setter: (String) -> Unit = ????
}
David Soroko
  • 8,521
  • 2
  • 39
  • 51

3 Answers3

14

Use t::x.setter, it returns a MutableProperty0.Setter<T>, which can be used as a function:

val setter = t::x.setter
setter("abc")
hotkey
  • 140,743
  • 39
  • 371
  • 326
  • 1
    Interestingly, this requires an additional dependency - `kotlin-reflect` – David Soroko Mar 18 '17 at 12:41
  • 1
    Is the code generated from `val getter: () -> String = t::x` differs from `val getter: () -> String = t::x.getter` – David Soroko Mar 18 '17 at 12:48
  • It is different, the latter has an extra method invocation on the `KMutableProperty0` interface (as you'd expect, this is what the code says). You can check this yourself by using `Show Kotlin bytecode` in IntelliJ (it's the `Tools -> Kotlin` menu). – zsmb13 Mar 18 '17 at 13:00
  • Shame about asymmetry between ref to getter and ref to setter – David Soroko Mar 18 '17 at 13:24
  • 1
    For the record, see the suggested usage here https://kotlinlang.org/docs/reference/reflection.html#bound-function-and-property-references-since-11 , which is symmetrical. – zsmb13 Mar 18 '17 at 15:07
  • Thank you @zsmb13 , in my example `t::x` is already a bound property .I don't see how the link you provided makes the usage symmetrical. – David Soroko Mar 19 '17 at 21:11
  • Well, as in the example uses `set` and `get` on the bound property instead of storing the getter and setter in a variable. – zsmb13 Mar 19 '17 at 21:16
6

The return type of t::x is KMutableProperty0<String>, which has a setter property, so you can do this:

val setter: (String) -> Unit = t::x.setter
setter("B")
println(getter()) // prints B now
zsmb13
  • 85,752
  • 11
  • 221
  • 226
1
t::x::set

This works without kotlin-reflect because it doesn't call any external methods, unlike t::x.setter

Still, the cleanest code is generated when using lambda syntax.

Agent_L
  • 4,960
  • 28
  • 30