Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Android SDK
Code

Programando Aplicaciones Funcionales en Kotlin: Lambdas, Seguridad de Nulos & Más

by
Length:LongLanguages:
This post is part of a series called Coding Android Apps in Kotlin.
Coding Functional Android Apps in Kotlin: Getting Started

Spanish (Español) translation by Nadia Castelli (you can also view the original English article)

En esta serie de tres partes, hemos estudiado a fondo Kotlin, un lenguaje de programación moderno para aplicaciones Android que corre sobre la Máquina Virtual Java (JVM).

Si bien Kotlin está lejos de ser el único lenguaje de programación alternativo diseñado para correr en la JVM, tiene mucho que ofrecer a los desarrolladores Android. Así que, si te has sentido frustrado con la parte Java del desarrollo Android, quizás quieras considerar darle una oportunidad a Kotlin.

En las primeras dos partes, estudiamos los siguientes temas:

  • Java vs. Kotlin: ¿Deberías Usar Kotlin en Desarrollo Android? En este artículo introductorio, hemos examinado qué tiene Kotlin para ofrecer a los desarrolladores Android, así como algunas potenciales desventajas que debes tener en cuenta antes de decidir si Kotlin es ideal para tí.

  • Programando Aplicaciones Funcionales en Kotlin: Primeros Pasos. En este post, hemos visto cómo configurar Android Studio para soportar código Kotlin, creamos una app Android escrita enteramente en Kotlin, nos familiarizamos con la sintaxis básica de Kotlin, y también vimos cómo el cambio hacia Kotlin puede hacer que nunca debas escribir otro findViewById.

Ahora que estás en posición de reemplazar las partes Java de tus proyectos con código Kotlin que produce el mismo resultado final, avancemos y veamos algunas áreas donde Kotlin tiene ventaja por sobre Java.

En este último artículo, exploraremos algunas de las características más avanzadas de Kotlin que te permiten ejecutar tareas que, o bien serían mucho más verborrágicas en Java, o bien no podrían realizarse con Java solamente.

Cuando llegues al final de este artículo, sabrás cómo utilizar Kotlin para recortar una tonelada de código repetitivo de tus proyectos, extender clases existentes con funcionalidad nueva, y lograr que esas frustrantes NullPointerException sean cosa del pasado.

No Más Nulos

¿Cuántas veces has incurrido en una NullPointerException al testear tu código? ¡Hoy, está bien claro que permitirles a los desarrolladores asignarle null a una referencia de objeto no fue la mejor elección de diseño! El intento de utilizar una referencia de objeto que tiene un valor nulo es una gran fuente de bugs a lo largo de muchos lenguajes de programación diferentes, incluyendo Java, De hecho, NullPointerException ha sido una fuente tan grande de irritación, que Java 8 añadió la anotación @NonNull específicamente para corregir este defecto en su sistema de tipado.

El problema yace en el hecho de que Java te permite establecer cualquier variable de un tipo de referencia a nulo—pero si en algún punto intentas usar una referencia que apunta a nulo, la variable no sabrá dónde "mirar" ya que el objeto no existe en realidad. En este punto, la JVM no puede continuar el camino normal de la ejecución—tu aplicación se detendrá, y encontrarás un NullPointerException. Tanto intentar invocar un método en una referencia nula como intentar acceder un campo de una referencia nula dispararán una NullPointerException.

Si has experimentado el dolor de los NullPointerException (¿no hemos pasado por eso todos en algún punto?), hay buenas noticias para tí: la seguridad de nulos está integrada en el lenguaje Kotlin. El compilador Kotlin no te permite asignarle un valor nulo a una referencia de objeto, ya que específicamente revisa tu código buscando la presencia de posibles objetos nulos durante la compilación Si el compilador Kotlin detecta que una NullPointerException puede ser producida en tiempo de ejecución, tu código fallará en tiempo de compilación.

El diseño de seguridad de nulos de Kotlin conlleva que (casi) nunca hallarás nulos ni NullPointerExceptions originadas por código Kotlin. La única excepción es si disparas una NullPointerException mediante el uso incorrecto de uno de los operadores especiales de Kotlin, o si utilizas uno de estos operadores para disparar una NullPointerException deliberadamente (exploraremos los operadores con más detalle, más adelante en este mismo artículo.

Seguridad de Nulos en Práctica

En Kotlin, todas las variables son consideradas no anulables por defecto, por lo cual el intento de asignar un valor nulo a una variable resultará en un error de compilación. Por ejemplo, el siguiente código no compilará:

Si realmente deseas que una variable acepte un valor nulo, necesitarás declarar explícitamente esa variable como anulable. Esto es exactamente lo contrario a Java, donde cada objeto se considera anulable por defecto, razón por la cual las NullPointerExceptions son tan comunes en Java.

Si quieres declarar explícitamente que una variable puede aceptar un valor nulo, deberás agregarle un ? al final del tipo de variable. Por ejemplo, el siguiente código compilará:

Cuando el compilador detecta este tipo de declaración, reconoce que esta es una variable anulable y la tratará de manera un poco diferente, más notablemente previniendo que tú invoques un método o accedas a una propiedad en esta referencia anulable, una vez más ayudándote a evitar esas molestas NullPointerExceptions. Por ejemplo, el siguiente código no compilará:

Aunque el diseño de Kotlin implica que es difícil hallar NullPointerExceptions originadas en el código Kotlin, si tu proyecto contiene una mezcla de Kotlin y Java, las porciones Java de tu proyecto aún pueden ser fuente de NullPointerExceptions.

Si estás trabajando con una mezcla de archivos Kotlin y Java (o tal vez específicamente necesitas introducir valores nulos en tu código Kotlin), Kotlin incluye varias operaciones especiales diseñadas para ayudarte a manipular cualquier valor nulo que encuentres, de forma elegante.

1. El Operador de Invocación Segura

El operador de invocación segura ?. proporciona una manera de lidiar con referencias que potencialmente pueden contener un valor nulo, asegurándose de que ninguna llamada a esta referencia resultará en una NullPointerException.

Cuando le agregas un operador de invocación segura a una referencia, se comprobará si esa referencia devuelve un valor nulo. Si lo es, se retorna null; de otra manera la referencia al objeto se utilizará como lo hayas indicado originalmente. Aunque podrías lograr el mismo efecto usando una sentencia if, el operador de invocación segura te permite efectuar el mismo trabajo en mucho menos código.

Por ejemplo, el siguiente código retornará a.size sólo si a no es nulo—de otra manera, devolverá null:

También puedes encadenar operadores de llamada segura:

Si cualquiera de las expresiones en esta serie es nula, luego el resultado será nulo; de lo contrario el resultado será el valor solicitado.

2. El Operador Elvis

Alguna vez tendrás una expresión que potencialmente pueda contener un valor nulo, pero no deseas emitir una NullPointerException aún si este valor realmente resulta nulo.

En estas situaciones, puedes utilizar el operador Elvis de Kotlin ?: para proveer un valor alternativo que será utilizado cuando el valor resulte ser nulo, lo cual es además una buena manera de prevenir la propagación de valores nulos en tu código.

Veamos un ejemplo del operador Elvis en acción:

Aquí, si el valor a la izquierda del operador Elvis no es nulo, se devuelve el valor del lado izquierdo (name). Pero si el valor a la izquierda del operador Elvis es nulo, entonces se retornará la expresión del lado derecho, que en esta instancia es N/A.

3. El Operador !!

Si alguna vez deseas forzar que tu código Kotlin emita una NullPointerException al estilo Java, puedes utilizar el operador !!. Por ejemplo:

Aquí, utilizamos el operador !! para afirmar que la variable firstName no es nula. Mientras firstName contenga una referencia válida, a la variable number se le asignará el length del string. Si firstName no contiene una referencia válida, Kotlin disparará una NullPointerException.

Expresiones Lambda

Una expresión lambda representa una función anónima. Los lambdas son una manera excelente de reducir la cantidad de código necesaria para ejecutar ciertas tareas que son repetitivas en el desarrollo Android—por ejemplo, la escritura de listeners y callbacks.

Java 8 introdujo expresiones lambda nativas, las cuales ahora soporta Android Nougat. Aunque esta funcionalidad no es algo exclusivo de Kotlin, aún así vale la pena echarles un vistazo. Además, si estás trabajando en un proyecto que contiene tanto código Kotlin como Java, ¡puedes utilizar expresiones lambda a lo largo de todo tu proyecto!

Una expresión lambda está compuesta por una serie de parámetros, un operador lambda (->) y el cuerpo de una función, dispuestos de la siguiente manera:

Al construir expresiones lambda en Kotlin, debes tener en cuenta las siguientes reglas:

  • La expresión lambda debe estar delimitada por llaves.

  • Si la expresión contiene cualquier parámetro, debes declararlo antes del símbolo ->.

  • Si estás trabajando con múltiples parámetros, debes separarlos con comas.

  • El cuerpo de la función va luego del signo ->.

El mayor beneficio de las expresiones lambda es que te permiten definir funciones anónimas y luego pasar estas funciones inmediatamente como una expresión. Esto te permite ejecutar muchas tareas comunes de desarrollo de manera más sucinta que en Java 7 y anteriores, ya que no necesitas escribir la especificación de la función en una clase abstracta o interfaz. De hecho, la ausencia de lambdas en Java 7 y anteriores es un gran motivo por el cual la manera de escribir listeners y callbacks es tan anticuada en Android.

Veamos un ejemplo común: añadir un click listener a un botón. En Java 7 y anteriores, esto típicamente require el siguiente código:

Sin embargo, las funciones lambda de Kotlin te permiten declarar un click listener usando una sola línea de código:

Esto ya resulta mucho más conciso y fácil de leer, pero podemos ir más lejos—si una función espera otra función como último parámetro, puedes pasarla por fuera de la lista dentro de los paréntesis:

Y si la función solo tiene un parámetro que es una función, puedes remover los paréntesis por completo:

Funciones de Extensión

De manera similar a C#, Kotlin te permite agregar nueva funcionalidad a clases preeexistentes que de otra manera no serías capaz de modificar. Entonces, si crees que a cierta clase le falta un método útil, ¿por qué no lo agregas tú, mediante una función de extensión?

Puedes crear una función de extensión poniéndole como prefijo el nombre de la clase que quieres extender al nombre de la función que estás creando.

Por ejemplo:

Fíjate que la palabra reservada this dentro de la función de extensión corresponde a la instancia de AppCompatActivity en que se invoca a .toast.

En este ejemplo, sólo necesitas importar las clases AppCompatActivity y Toast en tu archivo .kt, y entonces estás listo para utilizar la notación . en instancias de la clase extendida.

Cuando de desarrollo Android se trata, quizás encuentres funciones de extensión particularmente útiles para proveer a los ViewGroups la habilidad de inflarse a sí mismos, por ejemplo:

Entonces, en vez de escribir lo siguiente:

Simplemente puedes utilizar tu función de extensión:

Objetos Singleton

En Java, la creación de singletons ha sido típicamente muy verborrágica, requiriendo la creación de una clase con un constructor privado, y luego la creación de esa instancia como un atributo privado.

El resultado final es, por lo general, algo así:

Mas que declarar una clase, Kotlin te permite definir un objeto único, que es semánticamente lo mismo que un singleton, en una línea de código:

Luego puedes usar este singleton directamente, por ejemplo:

Conclusión

En este artículo, le echamos un vistazo en profundidad al diseño de seguridad de nulos de Kotlin, y vimos cómo puedes asegurarte de que tus proyectos Android permanezcan seguros en cuanto a nulidad, incluso cuando contienen una mezcla de código Java y Kotlin, mediante el uso de una variedad de operadores especiales. Además, vimos cómo puedes emplear expresiones lambda para simplificar ciertas tareas de desarrollo muy comunes en Android, y cómo agregar nueva funcionalidad a clases preexistentes.

Combinado con lo que aprendimos en Parte1: Java vs. Kotlin y Parte 2: Primeros Pasos, ya tienes todo lo que necesitas para empezar a desarrollar apps Android efectivas utilizando el lenguaje de programación Kotlin.

Diviértete con Kotlin, y por qué no, revisa algunos de nuestros otros cursos y tutoriales acerca de programación Android.

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.