mardi 15 mars 2022

Kotlin reflection: Is it possible to use KProperty1 and omit the class when the type is known through Generics

I'm working on mass database transformations. There are a lot of data classes, some of them with relationships between each other similar to the ones in SQL databases. These relationships are done by UUIDs, not by nesting data classes.

To lookup up in a list such an ID by some value in another property I use a function called lookup, which takes the KProperty1 of the field I have the value for, and the KProperty1 of the field with the ID to be returned:

import kotlin.reflect.KProperty1

fun <T> List<T>.lookup(lookup: KProperty1<T, String>, value: String, `return`: KProperty1<T, String>): String? =
  this
    .firstOrNull { lookup.get(it) == value }
    .run { if (this == null) null else `return`.get(this) }

Both fields and the lookup value are always of type String in all data classes, and therefore the return value of the lookup function is always String?.

I use it like this:

data class Test(
  val ID: String,
  val TEXT: String
  // more fields ...
)

val list = listOf(
  Test("1", "abc"),
  Test("2", "def"),
  Test("3", "ghi"),
  Test("4", "jkl")
)

val result = list.lookup(Test::TEXT, "ghi", Test::ID)

println(result)   // Output: 3

The question is: is there a way to omit the class name in the two parameters of the function? Basically something like this:

val result = list.lookup(::TEXT, "ghi", ::ID)

It could be done with strings, but there is of course the danger of misspelling:

val result = list.lookup("TEXT", "ghi", "ID")

The reason I ask – besides being curious – is that with thousands of such lookups – and often very long names – it just would look better:

val ... = storageLocationWarehouseSubItemList.lookup(StorageLocationWarehouseSubItem::TEXT, "ghi", StorageLocationWarehouseSubItem::ID)

val ... = storageLocationWarehouseSubItemList.lookup(::TEXT, "ghi", ::ID)




Aucun commentaire:

Enregistrer un commentaire