Migrando Android de Java a Kotlin

Qué es Kotlin?

"Kotlin es a Java lo que Switf es a Objective-C"

John Freddy Vega

Por qué migrar de Java a Kotlin?

Particularidades de Kotlin

Todo objeto es un Any, el nodo raíz de la jerarquía.

Particularidades de Kotlin

Para la definición de variables se utiliza val o var, y opcionalmente en frente y separado de : (dos puntos ) se define el tipo de dato.

val pi = 3.14159265358 //No se puede asignar después
var radio = 4 //Se puede asignar después

var diametro: Double = 0.0
diametro = radio * 2.0

Particularidades de Kotlin

Se habla de funciones en lugar de métodos.

class Calculadora {
    fun suma(num1: Double, num2: Double): Double {
        return num1 + num2
    }

    fun resta(num1: Double, num2: Double): Double = num1 - num2
}

Particularidades de Kotlin

Todo atributo o función por defecto es pública

class Calculadora {
    private fun suma(num1: Double, num2: Double): Double {
        return num1 + num2
    }

    fun resta(num1: Double, num2: Double): Double = num1 - num2
}

Particularidades de Kotlin

Toda expresión por defecto devuelve un Unit.

class Calculadora {
    private var resultado = 0.0

    fun suma(num1: Double, num2: Double) {
        resultado = num1 + num2
    }

    fun getResultado(): Double = resultado
}

// Retorna un kotlin.Unit
println("Suma: ${cal.suma(1.0, 2.0)}")

// Retorna un Double
println("Suma: ${cal.getResultado()}")
class Calculadora {
    private var resultado = 0.0

    fun suma(num1: Double, num2: Double) {
        resultado = num1 + num2
    }

    fun getResultado(): Double = resultado
}

// Retorna un kotlin.Unit
println("Suma: ${cal.suma(1.0, 2.0)}")

// Retorna un Double
println("Suma: ${cal.getResultado()}")

Particularidades de Kotlin

  • Kotlin tiene su propio compilador (genera archivos .class).
  • Kotlin se ejecuta sobre la JVM (Maquina Virtual de Java).

Null Safety ( ?, .?, !!, ?: )

var a: String = "abc"
a = null // error de compilación
var a: String? = "abc"
a = null // ok
/* 
Si b es null el length
también devolverá null 
*/
val l = a?.length

/*
Si b es null se lanzará
un NullPointerException
*/
val l = a!!.length
// Java
int l = a != null ? a.length : -1

// Kotlin (Operador Elvis)
val l = a?.length ?: -1

Caso 1

Caso 2

Caso 3

Caso 4

Caso 5

Expresiones

val a = "ABCD"
val l = if(a != null) a.length else -1

val l2 = when(a) {
    null -> -1
    else -> a.length
}

En Kotlin los condicionales pueden retornar valores directamente.

Data class

// Definición
data class Usuario (
    var nombre: String,
    var edad: Int,
    var ciudad: String
)

// Uso del data class
val unUsuario = Usuario("Carlos", 30, "Cali")
  • constructor de clase
  • get() y set() de cada propiedad

Infiere:

  • equals() y hasCode()
  • copy()

Hereda de Any:

Parámetros nombrados y

valores por defecto

// Definición
data class Usuario (
    var nombre: String,
    var edad: Int,
    var ciudad: String? = "Cali" // Definimos un valor por defecto
)

// Uso del data class
val usuario1 = Usuario("Carlos", 30)
val usuario2 = Usuario(nombre = "Carlos", edad = 30)

Con Kotlin podemos olvidarnos de tener que sobrecargar constructores o funciones

Template string

// Variable
val saludo = "Hola $nombre"

// Expresión
mTextView.setText("Hola $nombre, tu nombre tiene ${nombre.length} caracteres")

// Multilinea
val info = """
    Nombre: $nombre
    Edad: $edad
    Ciudad: $ciudad
    """
mTextView.setText(info)

Insertar variables directamente en la cadena (String) o incluso utilizar expresiones.

Property sintax

usuario.setNombre("Carlos Fernando")
mTextView.setText(usuario.getNombre())

De manera convencional con los get y set

usuario.nombre = "Carlos Fernando" // set
mTextView.text = usuario.nombre // get

Utilizando property sintax podemos omitir el uso explícito de las funciones set y get para simplemente asignar u obtener el valor de la variable.

Con property sintax

Smart casting

fun demo(a: Any) {
    if (a is String) {
        mTextView.text = a // x es casteada a String automaticamente
    }
}

El compilador detecta cuando verificamos el tipo de una variable y realiza el cast automático en caso de ser necesario.

Lambdas

when (c) {
    true -> yes()
    false -> {
        not()
        println("c es igual a false")
    }
}
var contador = 0
boton.addClickListener {
    contador++
    mTextView.text = "Clicks $contador"
}
fun setOnClickListener(listener: (view: View) -> Unit) {}

En un when

Función implicita

Función de orden superior

Lambdas

// Definición
class Calculadora {
    fun calcular(num1: Double, num2: Double,
                 op: (num1: Double, num2: Double) -> Double): Double = op(num1, num2)

    fun suma(num1: Double, num2: Double): Double = num1 + num2
    fun resta(num1: Double, num2: Double): Double = num1 - num2
    fun multiplcar(num1: Double, num2: Double): Double = num1 * num2
    fun dividir(num1: Double, num2: Double): Double = num1 / num2
}

val cal = Calculadora()
println("Suma: ${cal.calcular(1.0,2.0, cal::suma)}")
println("Resta: ${cal.calcular(1.0,2.0, cal::resta)}")
println("Multiplicación: ${cal.calcular(1.0,2.0, cal::multiplcar)}")
println("División: ${cal.calcular(1.0,2.0, cal::dividir)}")
  • Simplifican nuestro código al usar callbacks.
  • Pasar funciones como parámetros sin necesidad de crear interfaces.

Función de orden superior

Extensions  -  View Binding

import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : Activity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        // En lugar de findViewById<TextView>(R.id.textView)
        mTextView.text = "Hola, mundo!"
    }
}

Plugin kotlin-android-extensions

Y qué pasa si ya tengo un proyecto Android en Java?

Cuidado con los Null safety al interoperar!

java.lang.IllegalArgumentException: Parameter specified as non-null is null: 
method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull
// Kotlin
class Mensaje {
    //La forma correcta sería: fun mostrar(text: String?) {
    fun mostrar(text: String) { //java.lang.IllegalArgumentException
        //Hacer algo
    }
}

// Java
Mensaje.mostrar(null);
Made with Slides.com