Función genérica de extensión de Kotlin con types básicos sin API de reflexión

Tengo un object Java que tiene los methods getLong , getBoolean y getString . Intenté hacer una function de extensión genérica que tiene una function como último parámetro. Esencialmente envolviendo el try y catch y call a getString etc. que podría arrojar una exception. Descubrí que <reified T> como se establece al llamar, por ejemplo, getIt<Long>() { // do something with it } necesita la API de reflexión para descubrir T No pude hacer es verificar ni es Instancia. ¿Algunas ideas?

 // This is the non generic function version to get an idea inline fun JSONObject.getItLong(key: String, block: (value: Long) -> Unit) { try { block(this.getLong(key)) } catch (e: JSONException) { Log.w("${ javaClass.simpleName }KEx", e.message) } } 

El siguiente when no funciona.

 inline fun <reified T> JSONObject.getIt(key: String, block: (value: T) -> Unit) { try { when { Long is T -> { block(this.getLong(key) as T) } String is T -> { block(this.getString(key) as T) } // Boolean is T -> { block(this.getBoolean(key) as T) } // Boolean broken, does not have companion object? } } catch (e: JSONException) { Log.w("fetchFromJSONObject", e.message) } } 

Entonces, aparte del problema boolean, quería tener una forma genérica de llamar al tipo correcto de get mediante el uso de T Me encontré con la necesidad de agregar kaitlin reflection jar a classpath. Quería evitar eso si es posible.

ACTUALIZACIÓN1: la primera respuesta y respuesta usando un when con T::class realmente no funciona. Gracias por la idea y me ayudó a mirar nuevamente. El segundo que encontré fue "wordier" más de lo que quería, así que terminé con esta solución.

 inline fun <reified T> JSONObject.getIt(key: String, block: (value: T) -> Unit) { try { block(this.get(key) as T) } catch (e: JSONException) { Log.w("${ javaClass.simpleName }KEx", e.message) } } 

Esto se ve así: jsonObj.getIt<String>("error") { er = it } en comparación con jsonObj.getIt<String>("error", JSONObject::getString) { err = it }

ACTUALIZACIÓN2: Esto parece ser en última instancia un mejor enfoque, al less para mí y evita los problemas con el trabajo con medicamentos generics para cumplir con el objective

 inline fun JSONObject.unless(func: JSONObject.() -> Unit) { try { this.func() } catch (e: JSONException) { Log.w("${ javaClass.simpleName }KEx", e.message) } } 

Utilizando:

 jsonObj.unless { sDelay = getLong("s_delay") * 1000 wDelay = getLong("w_delay") * 1000 } jsonObj.unless { sam = getBoolean("sam") } jsonObj.unless { err = getString("error") } 

El operador kotlin toma un object a la izquierda y una reference de class a la derecha. Puede usar una simple comprobación de igualdad allí ya que tiene references de class en ambos lados.

T aún se desconoce en el momento de la compilation, así que tomar this.get*() as T no tiene mucho sentido. Ya habrás verificado el tipo en tu bloque when, así que podrías usarlo.

Como una cuestión de compleción, probablemente también desee include un bloque else en caso de que alguien llame a jsonObject.getIt<Date>(...) .

También incluí una segunda versión que toma un parámetro adicional para invocar, pero parece una versión less detallada de lo que originalmente quería. Toma la key , el accessor y el block , y funciona en cualquier acceso existente y nuevo agregado a JSONObject en el futuro sin reificación o modificaciones a la extensión.

 inline fun <reified T> JSONObject.getIt(key: String, block: (value: T) -> Unit) { try { when (T::class) { kotlin.Long::class -> block(this.getLong(key) as Long) kotlin.String::class -> block(this.getString(key) as String) kotlin.Boolean::class -> block(this.getBoolean(key) as Boolean) } } catch (e: JSONException) { Log.w("fetchFromJSONObject", e.message) } } inline fun <T> JSONObject.getIt(key: String, accessor: JSONObject.(String) -> T, block: (T) -> Unit) { try { accessor(key).let(block) } catch (e: JSONException) { Log.w("fetchFromJSONObject", e.message) } } 
  • ¿Cómo colocar una extensión de Kotlin en un file de class?
  • Función de extensión Kotlin en propiedad mutable
  • Cómo extender una class de datos con toString
  • Acceso a la function de extensión de Kotlin Campo privado de Java
  • Android Studio y Kotlin: reference no resuelta: también
  • Modificar "esto" en la function de extensión
  • En kotlin, cómo devolver una instancia definida por un parámetro de class genérico
  • Kotlin: ¿Cuando la function de extensión oculta la implementación pnetworkingeterminada de la class?
  • Funciones de extensión en types anotados
  • Tokens inesperados (uso; para separar expresiones en la misma línea)
  • Funciones de extensión para classs genéricas en Kotlin