Kotlin

Kotlin

Tutorial Kotlin: Operadores y expresiones

Kotlin operadores y expresiones te enseña todo sobre aritméticos, lógicos y relacionales, mejorando el flujo de datos en tus programas. Fórmate ahora.

Aprende Kotlin GRATIS y certifícate

Operadores aritméticos, lógicos y relacionales

En Kotlin, los operadores son símbolos que realizan operaciones sobre uno o más operandos. Los operadores aritméticos, lógicos y relacionales son fundamentales para manipular datos y controlar el flujo de un programa.

Los operadores aritméticos permiten realizar cálculos matemáticos. Los más comunes son:

  • + suma
  • - resta
  • * multiplicación
  • / división
  • % módulo (resto de una división)

Por ejemplo:

val suma = 10 + 5          // Resultado: 15
val resta = 10 - 5         // Resultado: 5
val multiplicacion = 10 * 5 // Resultado: 50
val division = 10 / 5      // Resultado: 2
val modulo = 10 % 3        // Resultado: 1

Es importante tener en cuenta el tipo de datos al realizar divisiones. Si ambos operandos son enteros, el resultado será un entero. Para obtener un resultado con decimales, al menos uno de los operandos debe ser de tipo Double o Float:

val divisionExacta = 10 / 3.0  // Resultado: 3.3333333333333335

Los operadores de asignación combinados simplifican las operaciones aritméticas que afectan a una variable y luego la asignan. Algunos ejemplos son:

  • += suma y asigna
  • -= resta y asigna
  • *= multiplica y asigna
  • /= divide y asigna
  • %= aplica módulo y asigna

Ejemplo de uso:

var numero = 10
numero += 5  // Equivalente a numero = numero + 5
println(numero)  // Resultado: 15

Los operadores relacionales comparan dos valores y devuelven un resultado Boolean (true o false). Los principales son:

  • == igual a
  • != no igual a
  • > mayor que
  • < menor que
  • >= mayor o igual que
  • <= menor o igual que

Ejemplo:

val a = 10
val b = 5
println(a == b)  // Resultado: false
println(a > b)   // Resultado: true

Los operadores lógicos permiten combinar expresiones lógicas y devuelven un valor Boolean. Son esenciales para estructuras de control como condicionales y bucles. Los más utilizados son:

  • && conjunción lógica (AND)
  • || disyunción lógica (OR)
  • ! negación lógica (NOT)

Ejemplo de uso:

val esAdulto = true
val tieneCarnet = false
val puedeConducir = esAdulto && tieneCarnet
println(puedeConducir)  // Resultado: false

En este ejemplo, la variable puedeConducir será true solo si esAdulto y tieneCarnet son true.

La negación lógica invierte el valor de una expresión Booleana:

val esMenorDeEdad = !esAdulto
println(esMenorDeEdad)  // Resultado: false

Kotlin también soporta el operador in para verificar si un elemento pertenece a una colección o rango:

val numero = 5
val rango = 1..10
println(numero in rango)       // Resultado: true
println(numero !in rango)      // Resultado: false

El operador in es muy útil en estructuras de control como bucles for o condicionales if.

Además, Kotlin introduce el operador Elvis ?:, que proporciona un valor por defecto en caso de que una expresión sea nula:

val nombre: String? = null
val longitud = nombre?.length ?: 0
println(longitud)  // Resultado: 0

En este caso, si nombre es null, longitud tomará el valor después de ?:, que es 0.

Finalmente, los operadores de comparación referencial permiten verificar si dos variables apuntan al mismo objeto en memoria:

  • === igual referencialmente
  • !== no igual referencialmente

Ejemplo:

val texto1 = "Kotlin"
val texto2 = "Kotlin"
println(texto1 == texto2)   // Resultado: true (contenido igual)
println(texto1 === texto2)  // Resultado: false (referencias diferentes)

En este ejemplo, aunque texto1 y texto2 tienen el mismo contenido, no son el mismo objeto en memoria.

Precedencia y asociatividad de operadores

En Kotlin, la precedencia de operadores determina el orden en el que se evalúan las expresiones que contienen múltiples operadores. La asociatividad define el orden en el que se agrupan los operadores con la misma precedencia. Comprender estos conceptos es fundamental para evitar resultados inesperados en cálculos y expresiones lógicas.

Los operadores con mayor precedencia se evalúan antes que los de menor precedencia. Si una expresión contiene operadores del mismo nivel de precedencia, la asociatividad determina el orden de evaluación: asociatividad izquierda significa que se evalúa de izquierda a derecha, mientras que asociatividad derecha implica una evaluación de derecha a izquierda.

Por ejemplo, considera la siguiente expresión aritmética:

val resultado = 10 + 5 * 2

En este caso, el operador * (multiplicación) tiene mayor precedencia que el operador + (suma). Por lo tanto, la multiplicación se evalúa primero:

  1. 5 * 2 produce 10.
  2. Luego, se suma 10 + 10, dando un resultado de 20.

Si se desea cambiar el orden de evaluación, se pueden utilizar paréntesis para alterar la precedencia:

val resultado = (10 + 5) * 2  // Resultado: 30

Ahora, la suma dentro de los paréntesis se evalúa primero, y luego el resultado se multiplica por 2.

La tabla de precedencia en Kotlin, de mayor a menor, incluye:

  • Operadores de incremento y decremento: ++ y --.
  • Operadores unarios: +, -, !, ~.
  • Cast seguro: as.
  • Multiplicación y división: *, /, %.
  • Suma y resta: +, -.
  • Operadores de rango: ...
  • Operadores de comparación: <, >, <=, >=.
  • Igualdad: ==, !=.
  • Operadores en intervalo: in, !in.
  • Operadores lógicos AND y OR bit a bit: &, |, ^.
  • Operadores lógicos: &&, ||.
  • Operadores de asignación: =, +=, -=, *=, /=, %=.

La asociatividad en Kotlin generalmente es de izquierda a derecha. Sin embargo, algunos operadores, como los de asignación (=), son asociativos a la derecha. Esto significa que en una expresión como:

val z = 5
val y = z
val x = y

La asignación se realiza de la siguiente manera: primero z se asigna a 5, luego y se asigna a z, y finalmente x se asigna a y.

Es crucial prestar atención al usar operadores lógicos. Por ejemplo:

val resultado = true || false && false

El operador && tiene mayor precedencia que ||, por lo que se evalúa primero:

  1. false && false produce false.
  2. Luego, true || false produce true.

Si se desea que el operador || se evalúe primero, se pueden usar paréntesis:

val resultado = (true || false) && false  // Resultado: false

Los operadores unarios como ++ y -- también tienen consideraciones de precedencia. Cuando se utilizan antes del operando (forma prefija), el incremento o decremento ocurre antes de la evaluación de la expresión. En la forma postfija, ocurre después:

var x = 5
val y = x++  // y = 5, x = 6

var m = 5
val n = ++m  // n = 6, m = 6

Entender la precedencia y asociatividad ayuda a escribir expresiones más claras y evita errores. Sin embargo, es una buena práctica utilizar paréntesis para hacer explícito el orden de evaluación, mejorando la legibilidad del código:

val resultado = (a + b) * (c - d) / e

De esta manera, otros desarrolladores podrán comprender fácilmente la intención detrás de las operaciones sin necesidad de recordar todas las reglas de precedencia.

Conversión y casting de tipos

En Kotlin, la conversión de tipos es un proceso esencial para manejar diferentes tipos de datos de manera segura y eficiente. A diferencia de algunos lenguajes donde las conversiones pueden ser implícitas, en Kotlin las conversiones numéricas deben realizarse de forma explícita mediante funciones específicas.

Para convertir un tipo numérico a otro, se utilizan funciones como toByte(), toShort(), toInt(), toLong(), toFloat(), toDouble(), entre otras. Por ejemplo:

val numeroEntero: Int = 42
val numeroDouble: Double = numeroEntero.toDouble()

En este ejemplo, se convierte el valor entero 42 a un valor de tipo Double utilizando la función toDouble().

Es importante tener en cuenta que las conversiones pueden llevar a pérdidas de precisión o información, especialmente al convertir de tipos de mayor capacidad a tipos de menor capacidad. Por ello, es fundamental realizar conversiones conscientes para evitar errores en el programa.

Kotlin también ofrece el concepto de casting para trabajar con tipos más generales o específicos dentro de una jerarquía de clases. El operador is se utiliza para comprobar si un objeto es de un tipo determinado:

fun identificar(objeto: Any) {
    if (objeto is String) {
        println("Es una cadena de texto de longitud ${objeto.length}")
    }
}

En este ejemplo, se verifica si objeto es una instancia de String. Si la condición es verdadera, Kotlin realiza un smart cast automáticamente, permitiendo acceder a las propiedades y métodos de String sin necesidad de un casting explícito.

Para realizar un casting explícito, se utiliza el operador as. Este operador intenta convertir una instancia a un tipo específico. Si la conversión no es posible, lanzará una excepción ClassCastException:

val cualquierObjeto: Any = "Kotlin"
val cadena: String = cualquierObjeto as String

Si existe la posibilidad de que el casting falle, es recomendable utilizar el casting seguro con as?, que devuelve null en caso de no poder realizar la conversión:

val numero: Int? = cualquierObjeto as? Int  // numero será null

El uso de as? es esencial para evitar excepciones y manejar de forma segura posibles conversiones fallidas.

Además, Kotlin incorpora funciones para trabajar con tipos genéricos y herencia. Cuando se trabaja con una jerarquía de clases, es común necesitar comprobar el tipo de un objeto y actuar en consecuencia. Por ejemplo:

open class Vehiculo
class Coche : Vehiculo()
class Moto : Vehiculo()

fun describir(vehiculo: Vehiculo) {
    when (vehiculo) {
        is Coche -> println("Es un coche")
        is Moto -> println("Es una moto")
        else -> println("Tipo de vehículo desconocido")
    }
}

En este caso, utilizamos el operador is dentro de una expresión when para identificar el tipo específico del objeto vehiculo.

Para evitar errores de casting y mejorar la seguridad del código, es buena práctica aprovechar el sistema de tipos de Kotlin y sus mecanismos de smart casting y comprobaciones de tipo en tiempo de compilación.

Cuando se trabaja con tipos nullables, es esencial manejar las posibles referencias nulas para evitar excepciones NullPointerException. Kotlin proporciona el operador de llamada segura ?. y el operador Elvis ?: para facilitar este manejo:

val cadenaNula: String? = null
val longitud: Int = cadenaNula?.length ?: 0

En este ejemplo, si cadenaNula es null, longitud tomará el valor 0. Esto permite manejar de forma elegante y segura las referencias nulas sin necesidad de realizar múltiples comprobaciones.

Entender y utilizar correctamente la conversión y casting de tipos en Kotlin es fundamental para escribir código robusto y libre de errores. Aprovechar las herramientas que ofrece el lenguaje, como las funciones de conversión, los operadores is y as, y los mecanismos de manejo de tipos nullables, mejora la calidad y fiabilidad de las aplicaciones desarrolladas.

Aprende Kotlin GRATIS online

Ejercicios de esta lección Operadores y expresiones

Evalúa tus conocimientos de esta lección Operadores y expresiones con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.

Todas las lecciones de Kotlin

Accede a todas las lecciones de Kotlin y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Introducción A Kotlin

Kotlin

Introducción Y Entorno

Instalación Y Primer Programa De Kotlin

Kotlin

Introducción Y Entorno

Tipos De Datos, Variables Y Constantes

Kotlin

Sintaxis

Operadores Y Expresiones

Kotlin

Sintaxis

Cadenas De Texto Y Manipulación

Kotlin

Sintaxis

Estructuras De Control

Kotlin

Sintaxis

Funciones Y Llamada De Funciones

Kotlin

Sintaxis

Clases Y Objetos

Kotlin

Programación Orientada A Objetos

Herencia Y Polimorfismo

Kotlin

Programación Orientada A Objetos

Interfaces Y Clases Abstractas

Kotlin

Programación Orientada A Objetos

Data Classes Y Destructuring

Kotlin

Programación Orientada A Objetos

Tipos Genéricos Y Varianza

Kotlin

Programación Orientada A Objetos

Listas, Conjuntos Y Mapas

Kotlin

Estructuras De Datos

Introducción A La Programación Funcional

Kotlin

Programación Funcional

Funciones De Primera Clase Y De Orden Superior

Kotlin

Programación Funcional

Inmutabilidad Y Datos Inmutables

Kotlin

Programación Funcional

Composición De Funciones

Kotlin

Programación Funcional

Monads Y Manejo Funcional De Errores

Kotlin

Programación Funcional

Operaciones Funcionales En Colecciones

Kotlin

Programación Funcional

Transformaciones En Monads Y Functors

Kotlin

Programación Funcional

Funciones Parciales Y Currificación

Kotlin

Programación Funcional

Introducción A Las Corutinas

Kotlin

Coroutines Y Asincronía

Asincronía Con Suspend, Async Y Await

Kotlin

Coroutines Y Asincronía

Concurrencia Funcional

Kotlin

Coroutines Y Asincronía

Evaluación

Kotlin

Evaluación

Accede GRATIS a Kotlin y certifícate

Certificados de superación de Kotlin

Supera todos los ejercicios de programación del curso de Kotlin y obtén certificados de superación para mejorar tu currículum y tu empleabilidad.

En esta lección

Objetivos de aprendizaje de esta lección

  1. Comprender el uso de operadores aritméticos, lógicos y relacionales en Kotlin.
  2. Aplicar operadores de asignación combinados para simplificar el código.
  3. Controlar el flujo del programa utilizando operadores lógicos.
  4. Diferenciar entre operadores de comparación de valores y referenciales.
  5. Usar correctamente la precedencia y asociatividad de operadores para evitar errores en cálculos.
  6. Implementar conversiones y casting de tipos con seguridad y eficacia.