¿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 .

  • Hacer ancho de dialog a pantalla completa
  • Incorrecto "esto" se usa en cierres nesteds
  • ¿Por qué no puedo usar @PublishedApi en typealias?
  • RxJava2: onComplete no llamado con flatMapIterable
  • ¿Cómo usar los wrappers de llamada para Intento Anko?
  • Android kotlin y Room Persistences library not building
  • muchos listview y cada uno contiene diferentes objects en Kotlin
  • ¿Cómo se soluciona la initialization del campo val con el proxy Spring Security?
  • Error al intentar usar la biblioteca de la sala. Error de SQL o database faltante
  • Corda: error = org.hibernate.InstantiationException: ningún constructor pnetworkingeterminado para la entidad
  • Kotlin: Declarar subclasss de una Actividad estática