Supongamos que tengo la siguiente definición de función.

fun<T> parse(a: Any): T = when (a) {
    is String -> a
    else -> false
}

Supuse que debería ser válido. Sin embargo, la interfaz IntelliJ IDEA muestra un error de falta de coincidencia de tipos

Linter error

Dicho esto, cambiaría el tipo de retorno de mi función de análisis a Cualquiera, ¿verdad? Entonces, ¿cuál es la diferencia entre usar Any type y Generics en Kotlin? ¿En qué casos debería usar cada uno de esos?

Leí la siguiente pregunta pero no entendí nada sobre star- proyección en Kotlin debido al hecho de que soy bastante nuevo.

4
Yajairo87 19 oct. 2017 a las 20:37

3 respuestas

La mejor respuesta

Su tipo de retorno se definió como T, pero no hay nada que asegure que T y a:Any estén relacionados. T puede ser más restrictivo que Any, en cuyo caso no puede devolver un valor booleano o lo que haya proporcionado para a.

Lo siguiente funcionará, cambiando el tipo de retorno de T a Any:

fun<T> parse(a: Any): Any = when (a) {
    is String -> a
    else -> false
}

Cualquier opción alternativa, si realmente desea devolver el tipo T:

inline fun<reified T> parse(a: Any): T? = when (a) {
    is T -> a
    else -> null
}
3
dillius 19 oct. 2017 a las 18:30

Su ejemplo no usa T y, por lo tanto, no tiene sentido hacerlo genérico de todos modos.

Piensa en esto: como cliente, pones algo en una función, p. un XML - ByteArray que se supone que la función debe analizar en un Object. Al llamar a la función, no desea que devuelva Any (La conversión apesta) pero desea que la función devuelva el tipo del objeto analizado. ESTO se puede lograr con genéricos:

fun <T> parse(xml: ByteArray): T {
     val ctx: JAXBContext = JAXBContext.newInstance()
     val any = ctx.createUnmarshaller().unmarshal(ByteArrayInputStream(xml))
     return any as T
}

val int = parse<Int>("123".toByteArray())
val string = parse<String>("123".toByteArray())

Mire las llamadas al método: le dice a los genéricos qué tipo se espera que se devuelva. El código no es útil y solo se supone que le dará una idea de los genéricos.

2
s1m0nw1 10 feb. 2018 a las 21:42

Supuse que debería ser válido

¿Por qué sería? Devuelve un String en una rama y un Boolean en la otra. Entonces, el tipo común para toda la expresión when es Any y eso es lo que el compilador (e IDEA) dice que es "encontrado". Su código también dice que debería ser T (que es "obligatorio").

Su método genérico debería funcionar para cualquier T, p. para Int, pero Any no es un subtipo de Int y, por lo tanto, el código no es válido.

Entonces, ¿cuál es la diferencia entre usar Any type y Generics en Kotlin?

Esto es como preguntar "cuál es la diferencia entre usar números y archivos": no tienen mucho en común en primer lugar. Utiliza genéricos para escribir código que puede funcionar con todos los tipos T (o con todos los tipos que satisfacen alguna restricción); usa Any cuando desea el tipo específico Any.

1
Alexey Romanov 19 oct. 2017 a las 20:25