¿Por qué aparece una discrepancia de tipo cuando bash devolver un valor para un parámetro genérico verificado?

En el siguiente código "Happy Halloween!" , 42 , etc. se marcan como "Tipo no coincidente". (Necesario: T, Found: String (o Int)), pero ¿no debería el comstackdor inferir que el valor de retorno es del tipo correcto de la verificación de tipo?

 interface Type<T> class StringType() : Type<String> class IntType1() : Type<Int> class IntType2(val a: Int, val b: Int) : Type<Int> fun <T> something(type: Type<T>): T = when (type) { is StringType -> "Happy Halloween!" is IntType1 -> 42 is IntType2 -> type.a * type.a + type.b * type.b + type.a * type.b else -> throw IllegalArgumentException() } 

Cuando el comstackdor aplica borrado de tipo, se definirá el tipo de retorno. Entonces, digamos, usted usa una Cadena … su método será como:

 fun something(type: Type<String>): String = when (type) { is StringType -> "Happy Halloween!" is IntType1 -> 42 //Wrong: you must return String! is IntType2 -> type.a * type.a + type.b * type.b + type.a * type.b else -> throw IllegalArgumentException() } 

Esto es: debe conocer su tipo de devolución en time de compilation . Si no sabes esto, tienes que decirle eso al comstackdor:

 fun <T> something(type: Type<T>): Any = when (type) { is StringType -> "blabla" is IntType1 -> 42 is IntType2 -> type.a * type.a + type.b * type.b + type.a * type.b else -> throw IllegalArgumentException() } 

Lo siento, este código no es lo que estás saltando, vas a hacer un yeso después de que se devuelva el método …

Pero puedes esto:

 fun <T> something(type: Type<T>): T = when (type) { is StringType -> type.b //is IntType1 -> 42 remove this! is IntType2 -> type.a * type.a + type.b * type.b + type.a * type.b else -> throw IllegalArgumentException() } 

asumiendo que type.a y type.b están parametrizados como T. Entonces su código funcionará bien.

Si simplifico un poco tu ejemplo:

 interface Type<T> fun <T> something(type: Type<T>): T = when (type) { is Type<String> -> "Happy Halloween!" else -> throw IllegalArgumentException() } 

el comstackdor ahora se queja de que: cannot check for instance of erased type

Entonces, el problema es que debido al borrado de tipo no hay diferencia entre Type<String> y Type<Int> en time de ejecución, por lo que el comstackdor no permitirá eso.

Puede intentar utilizar algo como Gson's TypeToken<T> o Jackson's TypeReference<T> Los documentos se refieren a esta publicación del blog que explica la idea: http://gafter.blogspot.ca/2006/12/super-type-tokens.html

El operador is , al igual que el operador instanceof de Java, se ejecuta en time de ejecución .

Por lo tanto, en time de compilation , el comstackdor no conoce el tipo real, por lo tanto, obtiene un error de compilation.

Aquí hay otro ejemplo simple:

 fun <T>f(t: T): T { if (t is Int) return 3 // comstacktion error else return t } 

Puedes escribir esto:

 interface Type<T> class StringType() : Type<String> class IntType1() : Type<Int> class IntType2(val a: Int, val b: Int) : Type<Int> inline fun <reified T> something(type: Type<T>): T { val result = when(type) { is StringType -> "Happy Halloween" is IntType1 -> 42 is IntType2 -> type.a * type.a + type.b * type.b + type.a * type.b else -> throw IllegalArgumentException() } return if (result is T) result else throw Exception() } 

Ejecutando lo siguiente:

 fun main(args: Array<String>) { println(something(StringType())) println(something(IntType1())) println(something(IntType2(2, 3))) } 

Te dará esta salida:

 Happy Halloween 42 19 

Obtenga más información sobre las funciones en línea y los parameters reificados aquí: Parámetros de types reificados .

  • La interfaz de Java SAM creada a partir de Kotlin da ClassCastException
  • Cómo burlarse de un object singleton Kotlin?
  • La secuencia de commands de Kotlin no puede acceder a los resources de META-INF (persistence.xml) desde el file jar
  • kotlin verificar campos de input
  • Cómo actualizar las classs de datos implementando una interfaz común
  • Cómo escribir la testing adecuada para el repository de interfaz reactiva que devuelve Observable solo cuando hay algún evento, cómo simular el desencadenamiento de ese evento
  • Android: Cómo hacer convertidores de tipo (para Habitación) generics para todos Lista de objects en Kotlin
  • RxJava, ¿Qué pasó si no llamo a disponer?
  • Crear una instancia de un tipo genérico en Kotlin
  • ¿Por qué unregisterReceiver () nunca llama aServiceDisconnected?
  • ¿Hay alguna manera de autocomplete los nombres de los arguments?