https://kotlinlang.org logo
#getting-started
Title
# getting-started
j

Johann Pardanaud

02/20/2023, 3:11 PM
I am probably missing something, how can you retrieve the class of a property represented by
KProperty
? For example, if I have:
Copy code
class Foo(val bar: Bar)
class Bar()

val fooInstance = Foo(Bar())

val kprop = fooInstance::bar
The type of
kprop
is
KProperty0<Bar>
. How can I obtain a
KClass<Bar>
from this property reflection? This would allow to reference some properties contained in the
Bar
class, or even some deeply nested properties. Basically, I’m trying to reproduce what a Key-Path expression does in Swift, but in a Kotlin way 🙂
1
s

Sam

02/20/2023, 3:20 PM
I’m not sure if it’s possible to unbind a bound reference 🤔 the original KEEP implies that the information about the receiver type isn’t actually retained
Foo::bar.instanceParameter?.type
would get you the type of
Foo
, but of course
fooInstance::bar
doesn’t have an instance parameter
e

ephemient

02/20/2023, 3:23 PM
is something like https://arrow-kt.io/docs/optics/ what you're trying to achieve?
j

Johann Pardanaud

02/20/2023, 3:48 PM
Arrow Optics seems to match what I would like to do yes. Is this the only solution? Because having to use an annotation could be an issue with some use cases, like protobuf generated code for example, because I’m not the one writing the code of the class. Basically, what I want is to create a function which is able to receive an object and a path to one of its properties (nested or not), then the function will be able to read and write the value of the referenced property. So, in Sam words, I think I might need “unbound references”? But it doesn’t seem feasible?
s

Sam

02/20/2023, 3:50 PM
If you can write and pass
Foo::bar
, which is an unbound reference, that will work fine. From your original post it sounds like you want to pass
fooInstance::bar
instead, which is what makes it tricky because that’s a bound reference and can’t (as far as I know) be converted to an unbound reference.
j

Johann Pardanaud

02/20/2023, 3:51 PM
Oh yeah sorry, I can perfectly use
Foo::bar
e

ephemient

02/20/2023, 3:52 PM
you could build a chain like
Copy code
class Foo(val bar: Bar)
class Bar(val baz: Int)

operator fun <T, U, V> ((T) -> U).plus(then: (U) -> V): (T) -> V = {
    then.invoke(this.invoke(it))
}

fun main() {
    val fooInstance = Foo(Bar(0))

    println((Foo::bar + Bar::baz)(fooInstance))
}
using unbound references, although I don't think that's very workable without supporting compiler plugins and libraries like Arrow Optics
💯 1
The + operator overload is a neat addition 👍
👍 1
j

Johann Pardanaud

02/20/2023, 4:00 PM
This is perfect @ephemient! Even if its quite lengthy, I can make something out of this. Thank you to both of you, you helped me understand a bit more how Kotlin reflection works. 🙏
d

David Kubecka

02/21/2023, 10:22 AM
What @ephemient wrote seems to be a general way of composing functions in Kotlin. I wonder whether there are any plans to put this into stdlib (you know, to promote the functional style a bit more).
3 Views