Una de las limitaciones que más frustran a los desarrolladores Java cuando utilizan genéricos es el no poder utilizar el tipo directamente.
Normalmente esto se solventa pasando la clase como parámetro de la función, haciendo el código más complejo y poco estético.
En Kotlin, gracias a las funciones inline
, de las que ya hemos hablado, podemos utilizar tipos reified
que nos permitirán utilizarlos dentro de las funciones.
¿Para qué sirve esto? Ya verás, te va a gustar.
Si todo esto te apasiona tanto como a mí, te animo a que te apuntes a mi training gratuito donde te contaré todo lo que necesitas para aprender a crear tus Apps Android en Kotlin desde cero.
Tipos reified
Como comentaba anteriormente, marcando un tipo como reified, tendremos la capacidad de utilizar ese tipo dentro de la función.
Es importante que la función que lo utilice sea inline, ya que el código necesita ser sustituido en el lugar desde el que se ejecuta para poder funcionar. El hecho de que no se puedan utilizar tipos en las funciones es una limitación de la Máquina Virtual de Java.
Navegando a una Activity
Este es el caso más típico aplicado a Android.
En Java, cuando llamamos a startActivity
, necesitamos pasar la clase de destino.
En Kotlin podemos simplificarlo simplemente tipando la función:
inline fun <reified T : Activity> Activity.startActivity() { startActivity(Intent(this, T::class.java)) }
Navegar a una Activity
ahora es tan sencillo como esto:
startActivity<DetailActivity>()
FindView con casting
Algo que mucha gente no utiliza en Java y que es muy útil es el tema de los genéricos para devolver objetos casteados al tipo correcto en función del tipo de variable.
En Java te puedes crear una función como esta:
public <T extends View> T findView(Activity activity, int id) { return (T) activity.findViewById(id); }
Y luego utilizarla de esta forma:
TextView textView = Utils.findView(activity, R.id.welcomeMessage);
Algo muy parecido se puede conseguir en Kotlin, sólo que más sencillo, como ya hemos visto, gracias a las funciones de extensión:
fun <T : View> Activity.findView(id: Int) = findViewById(id) as T val textView = activity.findView<TextView>(R.id.welcomeMessage)
Pero en ambos casos te vas a encontrar con el problema de que el compilador no puede estar seguro de que ese casting sea válido, pues no tiene acceso al tipo de T
. Así que te devolverá un warning.
Con los tipos reified te puedes evitar ese problema:
inline fun <reified T : View> Activity.findView(id: Int) = findViewById(id) as T
Conclusión
Con los tipos reified puedes conseguir resultados impensables en Java, y además conseguir hacer más seguras otras funciones que sí que son posibles en Java.
Evita volver a pasar un parámetro de tipo Class
a tus funciones.
Además, con las funciones de extensión te puedes crear nuevas funciones sobre frameworks como el de Android, que lo utilizan ya en gran parte de su API.
Y si quieres aprender a utilizar Kotlin para desarrollar tus propias Apps Android, te recomiendo que le eches un vistazo al training gratuito. ¡Reserva tu plaza !
Con la última función, al declarar findView(R.id.anyView) en el método onCreate, salta error diciendo que no tiene suficiente información para inferir el tipo T y que lo especifique explícitamente. ¿Hay algo incorrecto en el ejemplo?
Sí, el renderizador de código se había comido las partes de los tipos. Ya debería estar solucionado. Si tienes cualquier duda me dices, gracias!
Hola!
Quisiera saber porque si pueden haber funciones que afecten el framework de Android que todos usamos, porque no existe alguna biblioteca con estas funciones para que cualquiera lo usé? No entiendo bien ¿Por que todos tendríamos que implementar la misma función?
Gracias
Existe: https://developer.android.com/kotlin/ktx
Pero no están todas las funciones del mundo, eligen muy bien las que creen que les va a interesar a todo el mundo.