Inferir un tipo genérico de Mapa en Kotlin

Considere un método Java que infiere su tipo en class Java de la siguiente manera:

public <T> T readJson(Class<T> c) throws IOException { 

Esto permite hacer algo como esto:

 Map<String, String> map = foo.readJson(Map.class); 

En java advertirá sobre el lanzamiento sin marcar, pero funcionará correctamente. Sin embargo, en Kotlin, esto no será tan fácil, uno podría intentar usar:

 foo.readJson(Map::class.java) 

Sin embargo, si se requiere Map<String, String> , no funcionará:

 Type inference failed. Expected type mismatch. requinetworking Map<String, String> found Map<*, *>! 

También traté de definir una interfaz StringMap:

 interface StringMap : Map<String, String> 

Sin embargo, eso tampoco funciona, dará lugar a excepciones como esta:

 Cannot cast ...LinkedTreeMap to ...StringMap 

¿Cuál sería la forma correcta de hacer esto?

Kotlin no tiene nada como los types crudos de Java (que se dejaron en Java para compatibilidad con versiones anteriores), y el sistema de types por lo tanto no permite este tipo de asignaciones no verificadas implícitamente ( proyecciones en estrella , el concepto más cercano a types crudos en Kotlin, retener tipo de security).

Puede hacer un lanzamiento desactivado en Map<String, String> , expresando así que está al tanto de una posible discrepancia de tipo en el time de ejecución:

 @Suppress("UNCHECKED_CAST") val result = foo.readJson(Map::class.java) as Map<String, String> 

Puede suprimir la advertencia de conversión sin marcar para un scope más amplio que una sola statement.

Una mejora natural de esta solución es escribir una function util para ocultar el molde sin marcar:

 @Suppress("UNCHECKED_CAST") inline fun <reified T: Any> JsonReader.readJson(): T { val result = readJson(T::class.java) return result as T } 

Esta solución utiliza una function en línea con un parámetro de tipo reificado : la function se transforma y sustituye en cada uno de sus sitios de llamadas, con T reemplazado por el tipo especificado (o inferido) en el momento de la compilation.

Ejemplos de uso:

 val map = jsonReader.readJson<Map<String, String>>() 

 fun processMap(map: Map<String, String) { /* ... */ } processMap(jsonReader.readJson()) // Map<String, String> is infernetworking for this call 
  • Kotlin: ¿Qué hacen los operadores más / less unarios con los numbers?
  • Kotlin: Pase el object en function como reference y cambie su instancia
  • Kotlin: método genérico y para bucle preguntando por iterador ()
  • Generar diagtwig de class de Kotlin
  • Room y Kotlin: get "Cada variable de vinculación en la consulta debe tener un parámetro de método coincidente".
  • DuplicateFileException en la compilation de apk usando Kotlin
  • Referencia de KClass para valores anulables
  • ReferenceError: ok no está definido en QUnitAsserter.assertTrue en Kotlin Javascript
  • Las annotations en time de ejecución anotadas en una class archivada en kotlin no se generan correctamente
  • Convierta la aplicación de Android Kotlin utilizando Project Astoria
  • Cómo degradar Kotlin en Intellij 15