Me preguntaba por qué, ya if (x is MyGeneric<Int>) { ... }
se bloqueará debido al borrado de tipo, como? obras. Quiero decir, ¿no se podría implementar A is B
como (A as? B).let { if (it == null) false else true }
? En caso afirmativo, ¿por is
los controles no pueden funcionar con los genéricos? En caso negativo, ¿en qué difiere?
Cuando lanza una clase que tiene tipos genéricos, la conversión siempre tendrá éxito si el tipo genérico es lo único que está mal. Y el borrado de tipo, con el que parece estar familiarizado, es la razón. En tiempo de ejecución, List<String>
y List<Foo>
son exactamente lo mismo debido al borrado de tipos, por lo que la conversión entre ellos siempre tendrá éxito.
Por lo tanto, una conversión segura no lo protege de equivocarse en el tipo genérico, solo en el tipo de clase.
as?
obras
No, no lo hace. as?
no devuelve nulo, incluso cuando los argumentos de tipo genérico no son compatibles:
val strings = listOf("x", "y") val ints = strings as? List<Int>
El código anterior se compilará y ejecutará sin ningún error. Solo arrojará una excepción, cuando realmente saque cosas de ints
e intente usarlas como Int
s. La razón por la que esto sucede es, como dijiste, el borrado de tipos.
is
podría haber diseñado para funcionar de la misma manera as?
- evaluando como true
incluso cuando los argumentos de tipo genérico no son compatibles:
val strings = listOf("x", "y") strings is List<Int> // this could be designed to evaluate to true
Los diseñadores de Kotlin decidieron prohibir x is Foo<T>
, pero permitir x as? Foo<T>
.
Después de todo, "verificar el tipo" y "convertir el tipo" vienen con diferentes expectativas. Si me pregunta si una instancia de List<Int>
es de tipo List<Int>
, sería muy inesperado si dijera que sí. Por otro lado, si me pide que convierta una instancia de List<Int>
en List<String>
y lo hice con éxito (aunque sin verificar el contenido de la lista), eso no es tan inesperado. Después de todo, hice lo que me pediste.
Ahora para responder a tu pregunta:
Quiero decir, ¿no se podría implementar A es B como
(A as? B).let { if (it == null) false else true }
? En caso afirmativo, ¿poris
los controles no pueden funcionar con los genéricos?
Podría, pero esto produciría algunos comportamientos bastante inesperados, como se discutió en el párrafo anterior. Por lo tanto, está diseñado para no permitirlo.