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) } } 
  • Métodos de interfaz de anulación de Android kotlin dentro del método onCreateView ()
  • Kotlin: ¿funciones de extensión y types de plataforma?
  • Cómo corregir la firma del método de extensión genérico en kotlin para resolver "Falló la inferencia de tipo" en kotlin
  • ¿Cómo verificar la class "instanceof" en kotlin?
  • Función de extensión Kotlin en propiedad mutable
  • Modificar "esto" en la function de extensión
  • Kotlin: Cómo extender la class enum con una function de extensión
  • Kotlin: ¿Cómo ejecutar methods de service en el context de una class de transacción?
  • Método de extensión de Kotlin como alias para el nombre de método largo?
  • ¿Puedo enviar la function de extensión a través del parámetro de function?
  • Cómo extender una class de datos con toString