El pasado mes de mayo se celebró la edición anual de Google I/O, el evento donde la multinacional presenta las primicias que estarán a disposición de los usuarios de la gran G a corto y medio plazo, y también las novedades para los desarrolladores de las diferentes tecnologías relacionadas con su ecosistema.

Para Android, se presentaron características de la futura versión del sistema operativo, Android O: la nueva versión de la librería support, instant apps, las nuevas librerías para dar soporte a las arquitecturas de aplicaciones. Sin embargo, para mí y para muchos desarrolladores más, el anuncio más llamativo de todos fue la apuesta oficial por Kotlin como lenguaje de desarrollo Android.

¿Qué significa esto? Pues que a partir de la próxima versión 3.0 de Android Studio, podremos desarrollar aplicaciones para Android usando este lenguaje de programación, totalmente integrado por el IDE. Pero entremos un poco en materia.

 

¿QUÉ ES KOTLIN?

Kotlin es un lenguaje de programación de tipado estático que corre sobre la JVM que ha sido desarrollado por JetBrains, responsables de IntelliJ, IDE en el que se basa Android Studio (¡menuda casualidad!).

Aunque lleva fraguándose desde el año 2011, en febrero de 2016 se lanzó su primera versión estable 1.0 y este pasado marzo ya se actualizó a 1.1. Nació con la idea de sustituir a Java pero siendo totalmente interoperable con él y todo su ecosistema (para facilitar así la migración).

 

¿QUÉ APORTA KOTLIN QUE NO NOS DA JAVA?

Para dar una muestra de las bondades de Kotlin frente a Java, me voy a apoyar en las cuatro características que se mencionan en el libro “Kotlin for Android Developers” de Antonio Leiva, uno de los mayores referentes dentro de la comunidad Android y uno de los máximos promulgadores del nuevo lenguaje oficial de desarrollo.

  1. Expresividad
  2. Seguridad frente a nulos
  3. Funciones de extensión
  4. Programación funcional

 

1. EXPRESIVIDAD

Si queremos declarar una clase completa en Java tenemos que definir los getter, setter, toString, hashCode y equals. Por ejemplo, si definimos la clase “Dog”, tendríamos la siguiente clase Java:

public class Dog {
    
    private Long id;
    private String name;
    private String owner;
    private String breed;
 
    public Dog(Long id, String name, String owner, String breed) {
        this.id = id;
        this.name = name;
        this.owner = owner;
        this.breed = breed;
    }
 
    public Long getId() {
        return id;
    }
 
    public void setId(Long id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getOwner() {
        return owner;
    }
 
    public void setOwner(String owner) {
        this.owner = owner;
    }
 
    public String getBreed() {
        return breed;
    }
 
    public void setBreed(String breed) {
        this.breed = breed;
    }
 
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
 
        Dog dog = (Dog) o;
 
        if (id != null ? !id.equals(dog.id) : dog.id != null) return false;
        if (name != null ? !name.equals(dog.name) : dog.name != null) return false;
        if (owner != null ? !owner.equals(dog.owner) : dog.owner != null) return false;
        return breed != null ? breed.equals(dog.breed) : dog.breed == null;
 
    }
 
    @Override
    public int hashCode() {
        int result = id != null ? id.hashCode() : 0;
        result = 31 * result + (name != null ? name.hashCode() : 0);
        result = 31 * result + (owner != null ? owner.hashCode() : 0);
        result = 31 * result + (breed != null ? breed.hashCode() : 0);
        return result;
    }
 
    @Override
    public String toString() {
        return "Dog{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", owner='" + owner + '\'' +
                ", breed='" + breed + '\'' +
                '}';
    }
}

 

Como vemos, tenemos muchísimo código repetitivo (como casi todo en Java) para definir una clase. Sin embargo, todo eso lo podemos hacer en Kotlin de una forma muchísimo más sencilla.

data class Dog(var id: Long, var name: String, var owner: String, var breed: String)

 

Esto es sólo un ejemplo de que con mucho menos código podemos hacer muchas más cosas en Kotlin que en Java, y de una forma muy clara y legible.

 

2. SEGURIDAD FRENTE A NULOS

Cuando desarrollamos en Java, muchísimo código es defensivo. Esto supone que tenemos que comprobar continuamente cuándo algún objeto es nulo si no queremos encontrarnos con el típico error en tiempo de ejecución NPI. Sólo los tipos nativos no son nulos.

Dog dog = null;
Log.println(Log.INFO, "TEST", dog.getName());
#Este código se puede compilar, pero produce un NPI en tiempo de ejecución

 

Kotlin, sin embargo, como muchos otros lenguajes modernos, es seguro frente a nulos. Es decir, tenemos que especificar explícitamente cuándo un objeto puede ser nulo.

val dog1: Dog = Dog(lL, “Toby”, “Javi”, “Galgo”)
var dog2: Dog? = null
 
#Me permite compilar
dog1.print()
 
#No me permite compilar al no comprobar que es nulo
dog2.print()
 
#Con el operador ? si me deja hacerlo
dog2?.print()
 
#O como en Java
 
if(dog2 != null){
	dog2.print() 
}
#Ahora si compila, al estar dentro de un bloque donde se ha comprobado que no es nulo.
 
#Podemos usar el operador Elvis para dar un valor cuando la variable es nula
var name = dog2.name ?: “Desconocido”

 

3. FUNCIONES DE EXTENSIÓN

Con Kotlin podemos añadir nuevas funciones a cualquier clase de Java o Android con las funciones de extensión, que se entienden y son mucho más intuitivas que las típicas clases de utilidades que todo programador ha usado alguna vez.

Podemos, por ejemplo, añadir un método a un fragment para que muestre un toast de la siguiente forma:

fun Fragment.toast(message: CharSequence, duration: Int = Toast.LENGHT_SHORT){
	Toast.makeText(activity, message, duration).show
}
 
#Y lo podemos usar dentro de un fragment directamente:
toast.dog1.name

 

4. PROGRAMACIÓN FUNCIONAL

Realmente, con Java 8 podemos usar programación funcional con lambdas, pero éstas están bastante limitadas con respecto a todo el potencial que nos aporta Kotlin.

Dentro de un fragment con un TextView podemos implementar el típico onClickListener con una lambda de la siguiente forma:

textView.setOnClickListener {toast.dog2?.name}

 

EL FUTURO DE Y CON KOTLIN

Esto es sólo una pequeña muestra de todo el potencial que tiene este joven pero maduro lenguaje de programación. Podría contar más de las funciones sobre colecciones, properties, delegados, corrutinas, smartcast, etc., pero aún es un mundo por descubrir.

Actualmente, el equipo de desarrollo de Jetbrains está trabajando en Kotlin/Native, lo que significa que, en un futuro próximo, Kotlin podrá ser lenguaje para el desarrollo de aplicaciones iOS. Tendremos así la posibilidad de reutilizar código fuente con Android (¡qué bien suena!), sistemas embebidos o IoT (Arduino, por ejemplo), BigData, servicios, desarrollo de videojuegos, etc. En fin, el futuro.