How to get the name of a variable in Kotlin?
Asked Answered
P

3

25

I have a Kotlin class in my application with a lot of attributes, what I want to build is a method that stores the variable name in a dictionary. The dictionary looks like this:

HashMap<String, Pair<Any, Any>>()

The purpose of this is to store the changes made to a certain attribute, I store the name of the variable as the key and in the Pair I store the old value and the new value. To notify a change I use the Observer pattern. So whenever a setter is called from an attribute a change will be notified and stored to the dictionary.

The code below results in the folowing:

var person = Person("Harry", 44)
person.age = 45

HashMap("age", (44, 45))

Right now I am just hardcoding the variable name in as a String, so my question is:

How to dynamicly get the name of a variable in Kotlin?

I saw the same question in Java: Java Reflection: How to get the name of a variable?

Also some other questions about the same topic claiming it is not possible: Get the name property of a variable

I can understand that it is not possible to get the name of a variable, because the compiler simple doesn't have that information, but I am still currious to see if others have any sollution for this problem.

Photoflash answered 7/11, 2018 at 11:4 Comment(2)
do you know already what delegated properties are?Chroma
No I was not aware of delegated properties, looks nice I will take a look at that, thanks.Photoflash
P
8

I think delegate properties is the solution to my problem:

class Delegate {
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
    return "$thisRef, thank you for delegating '${property.name}' to me!"
}

operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
    println("$value has been assigned to '${property.name}' in $thisRef.")
  }
}

Credits go to: Roland
Source: https://kotlinlang.org/docs/reference/delegated-properties.html

Photoflash answered 7/11, 2018 at 11:20 Comment(1)
well... maybe it suffices your needs, but be sure to also look at the observable and properties in a map variants, which might even be more appropriate or easier to implement.Chroma
H
44

As stated in the Kotlin documentation about Reflection:

val x = 1

fun main() {
    println(::x.get())
    println(::x.name) 
}

The expression ::x evaluates to a property object of type KProperty<Int>, which allows us to read its value using get() or retrieve the property name using the name property.

Hydrolyte answered 7/11, 2018 at 14:55 Comment(1)
How to do this with this?Corrugate
F
9

Use memberProperties to get the names of the class attributes and others properties. For instance:

YourClass::class.memberProperties.map {
 println(it.name)
 println(it.returnType)
}
Frasier answered 31/10, 2019 at 18:37 Comment(1)
How can i get the value of the field as well ?Spelldown
P
8

I think delegate properties is the solution to my problem:

class Delegate {
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
    return "$thisRef, thank you for delegating '${property.name}' to me!"
}

operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
    println("$value has been assigned to '${property.name}' in $thisRef.")
  }
}

Credits go to: Roland
Source: https://kotlinlang.org/docs/reference/delegated-properties.html

Photoflash answered 7/11, 2018 at 11:20 Comment(1)
well... maybe it suffices your needs, but be sure to also look at the observable and properties in a map variants, which might even be more appropriate or easier to implement.Chroma

© 2022 - 2024 — McMap. All rights reserved.