If converting between a property with your enum
value and another property of type String
enough, this can easily be done in a flexible way using Kotlin delegated properties .
To put it briefly, you can implement a delegate for String
properties that does the conversion and actually gets / sets the value of another property that stores enum
values and then delegates the String
property to it.
One possible implementation would look like this:
class EnumStringDelegate<T : Enum<T>>( private val enumClass: Class<T>, private val otherProperty: KMutableProperty<T>, private val enumNameToString: (String) -> String, private val stringToEnumName: (String) -> String) { operator fun getValue(thisRef: Any?, property: KProperty<*>): String { return enumNameToString(otherProperty.call(thisRef).toString()) } operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) { val enumValue = java.lang.Enum.valueOf(enumClass, stringToEnumName(value)) otherProperty.setter.call(thisRef, enumValue) } }
Note. This code requires that you add the Kotlin reflection API, kotlin-reflect
, as a dependency on your project. Using Gradle, use the compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
.
This will be explained below, but first let me add a convenience method to avoid instantiating directly:
inline fun <reified T : Enum<T>> enumStringLowerCase( property: KMutableProperty<T>) = EnumStringDelegate( T::class.java, property, String::toLowerCase, String::toUpperCase)
And a usage example for your class:
Now the explanation:
When you write var weightUnit: String by enumStringLowerCase(UserData::weightUnitEnum)
, you delegate the String
property to the constructed delegate object. This means that when accessing a resource, delegate methods are called instead. And the delegate object, in turn, works with the weightUnitEnum
property under the hood.
The added convenience function eliminates the need to write UserData::class.java
on the property declaration site (using the reified type parameter) and provides conversion functions for EnumStringDelegate
(you can create other functions with different transformations at any time or even create a function that receives functions conversions like lambdas).
Basically, this solution saves you from the code of the template, which represents a property of the enum
type as a String
property, taking into account the logic of conversion, and also allows you to get rid of excess code in your enum
if you no longer use it.
Using this method, you can implement any other conversion between properties, for example, the number that you specified in the timestamp.