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
.
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")
Bloque Try-Catch-Finally:
try
, catch
y opcionalmente finally
.leerArchivo(nombreArchivo: String)
, se intenta abrir y leer un archivo utilizando FileReader
y BufferedReader
.Catch para Excepciones Específicas:
catch
, se manejan excepciones específicas como FileNotFoundException
y IOException
.Finally:
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:
throw new
seguido de la excepción a lanzar.Captura y Manejo de Excepciones:
catch
pueden ser procesadas para proporcionar retroalimentación o tomar acciones correctivas apropiadas en base al tipo de excepción.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
).
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}")
}
Importación de Clases y Objetos:
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
:
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
:
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.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
).
// 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)
}
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.