Manejo de Errores y Excepciones

Manejo de excepciones en Scala

El manejo de excepciones en Scala se basa en las mismas estructuras fundamentales que en otros lenguajes de programación orientados a objetos. Las excepciones se lanzan y capturan utilizando bloques try, catch y finally.

Código Completo

				
					import java.io._

// Función que lanza una excepción
def leerArchivo(nombreArchivo: String): Unit = {
  val archivo = new FileReader(nombreArchivo)
  try {
    val buffer = new BufferedReader(archivo)
    var linea = buffer.readLine()
    while (linea != null) {
      println(linea)
      linea = buffer.readLine()
    }
  } catch {
    case e: FileNotFoundException => println(s"Archivo no encontrado: $nombreArchivo")
    case e: IOException => println(s"Error de E/S al leer el archivo: $nombreArchivo")
  } finally {
    archivo.close()
  }
}

// Uso de la función para leer un archivo
leerArchivo("archivo.txt")

				
			

Explicación del Código

  • Bloque Try-Catch-Finally:

    • En Scala, el manejo de excepciones se realiza utilizando bloques try, catch y opcionalmente finally.
    • En leerArchivo(nombreArchivo: String), se intenta abrir y leer un archivo utilizando FileReader y BufferedReader.
  • Catch para Excepciones Específicas:

    • Dentro del bloque catch, se manejan excepciones específicas como FileNotFoundException y IOException.
  • Finally:

    • El bloque finally se utiliza para ejecutar código que debe ejecutarse independientemente de si se lanzó una excepción o no. En este caso, se asegura de cerrar el archivo abierto (archivo.close()).
  • Lanzamiento de Excepciones:

    • Las excepciones en Scala pueden ser lanzadas explícitamente utilizando throw new seguido de la excepción a lanzar.
  • Captura y Manejo de Excepciones:

    • Las excepciones capturadas dentro del bloque catch pueden ser procesadas para proporcionar retroalimentación o tomar acciones correctivas apropiadas en base al tipo de excepción.

Try, Success y Failure

En Scala, Try, Success y Failure son clases y objetos utilizados para manejar operaciones que pueden resultar en éxito o fracaso (lanzar una excepción). Try encapsula el resultado de una operación, que puede ser exitosa (Success) o fallida (Failure).

Código Completo

				
					import scala.util.{Try, Success, Failure}

// Función que simula una operación que puede lanzar una excepción
def dividir(a: Int, b: Int): Try[Int] = {
  Try(a / b)
}

// Uso de la función dividir con pattern matching para manejar resultados
dividir(10, 2) match {
  case Success(resultado) => println(s"Resultado de la división: $resultado")
  case Failure(excepcion) => println(s"Error al dividir: ${excepcion.getMessage}")
}

// Intento de división que provocará una excepción
dividir(10, 0) match {
  case Success(resultado) => println(s"Resultado de la división: $resultado")
  case Failure(excepcion) => println(s"Error al dividir: ${excepcion.getMessage}")
}

				
			

Explicación del Código

  • Importación de Clases y Objetos:

    • Se importan las clases Try, Success y Failure del paquete scala.util para manejar resultados de operaciones que pueden lanzar excepciones.
  • Función dividir:

    • dividir(a: Int, b: Int): Try[Int] simula una operación de división que puede resultar en éxito (Success) si b no es cero, o en fracaso (Failure) si b es cero (provocando una excepción ArithmeticException).
  • Pattern Matching con Try:

    • Se utiliza pattern matching con Try para manejar los resultados de la función dividir. Si la operación es exitosa (Success(resultado)), se imprime el resultado de la división. Si la operación falla (Failure(excepcion)), se imprime el mensaje de error obtenido de la excepción.
  • Manejo de Excepciones con Failure:

    • Se demuestra cómo Failure captura y proporciona acceso a la excepción lanzada durante la operación de división por cero.
  • Beneficios de Try:

    • Try simplifica el manejo de operaciones que pueden lanzar excepciones, permitiendo un código más claro y conciso utilizando pattern matching para manejar diferentes resultados de manera explícita.

Validación con Either y Option

En Scala, Either y Option son opciones comunes para manejar resultados que pueden estar presentes (Some para Option) o ausentes (None para Option) y para representar resultados que pueden ser exitosos (Right para Either) o con errores (Left para Either).

Código Completo

				
					// Función para validar un número positivo utilizando Option
def validarNumeroOption(num: Int): Option[String] = {
  if (num > 0) Some(s"$num es un número positivo.")
  else None
}

// Uso de la función validarNumeroOption
val resultadoOption = validarNumeroOption(10)
resultadoOption match {
  case Some(mensaje) => println(mensaje)
  case None => println("El número no es positivo.")
}

// Función para validar un número positivo utilizando Either
def validarNumeroEither(num: Int): Either[String, Int] = {
  if (num > 0) Right(num)
  else Left("El número no es positivo.")
}

// Uso de la función validarNumeroEither
val resultadoEither = validarNumeroEither(10)
resultadoEither match {
  case Right(numero) => println(s"El número validado es: $numero")
  case Left(mensaje) => println(mensaje)
}

				
			

Explicación del Código

  • Validación con Option:

    • Option es utilizada en validarNumeroOption(num: Int): Option[String] para validar si un número es positivo. Retorna Some(mensaje) si el número es positivo y None si no lo es.
  • Uso de Option:

    • resultadoOption es el resultado de llamar validarNumeroOption(10). Con pattern matching, se imprime el mensaje si el número es positivo (Some(mensaje)) o se indica que no lo es (None).
  • Validación con Either:

    • Either es usado en validarNumeroEither(num: Int): Either[String, Int] para validar si un número es positivo. Retorna Right(num) si el número es positivo y Left(mensaje) si no lo es.
  • Uso de Either:

    • resultadoEither es el resultado de llamar validarNumeroEither(10). Con pattern matching, se imprime el número validado (Right(numero)) o el mensaje de error (Left(mensaje)).
  • Diferencias entre Option y Either:

    • Option es usado cuando el resultado puede estar presente (Some) o ausente (None), mientras que Either es utilizado cuando el resultado puede ser exitoso (Right) o contener un error (Left).
  • Aplicaciones:

    • Option es útil para representar valores que pueden ser nulos, mientras que Either es ideal para situaciones donde se necesita retornar un valor exitoso o un mensaje de error explicativo.