Saltar al contenido principal

switch expression

Anteriormente, aprendimos sobre la estructura switch case que nos ayuda a asignar o ejecutar una l贸gica espec铆fica de acuerdo al resultado de la comparaci贸n evaluada.

Dart 3 introdujo la expresi贸n switch que es una mejora al cl谩sico switch case. Esta versi贸n mejorada permite utilizar el switch como una expresi贸n, lo que significa que puede producir un valor y asignarse a una variable o usarse en cualquier lugar donde se espere una expresi贸n

Veamos un sencillo ejemplo, suponiendo que el primer d铆a de la semana es lunes y es el d铆a uno, martes es el d铆a dos y as铆 sucesivamente hasta llegar al domingo. Dado un n煤mero entero, queremos imprimir a que d铆a corresponde. Usando el cl谩sico switch case, el c贸digo se ver谩 as铆:

// Ejemplo usando el cl谩sico switch case
void main() {
final diaActual = obtenerDia(5);
print('Hoy es $diaActual'); // Hoy es Viernes
}

String obtenerDia(int dia) {
switch (dia) {
case 1:
return 'Lunes';
case 2:
return 'Martes';
case 3:
return 'Mi茅rcoles';
case 4:
return 'Jueves';
case 5:
return 'Viernes';
case 6:
return 'S谩bado';
case 7:
return 'Domingo';
default:
return 'El dia no existe';
}
}

En el c贸digo anterior, hemos definido m煤ltiples case con todos los valores de los d铆as de la semana posibles y adem谩s incluimos un default para los valores que no coincidan con alguno de los d铆as de la semana.

Utilizando la expresi贸n switch, podemos hacer el c贸digo m谩s compacto y f谩cil de leer:

// Ejemplo usando la nueva expresi贸n switch
void main() {
final diaActual = obtenerDia(5);
print('Hoy es $diaActual'); // Hoy es Viernes
}

String obtenerDia(int dia) {
return switch (dia) {
1 => 'Lunes',
2 => 'Martes',
3 => 'Mi茅rcoles',
4 => 'Jueves',
5 => 'Viernes',
6 => 'S谩bado',
7 => 'Domingo',
_ => 'El dia no existe',
};
}

En este ejemplo, la expresi贸n dia se eval煤a y se compara con distintos casos utilizando la sintaxis =>. Si el valor de dia es 1, el resultado es 'Lunes'. El guion bajo _ se utiliza como un caso por defecto para cualquier otro valor que no coincida con los casos anteriores.

Coincidencia de patrones ( pattern matching)

La coincidencia de patrones es una t茅cnica que permite verificar si un valor cumple con un patr贸n espec铆fico y realizar acciones en funci贸n de ello. Se utiliza para realizar comparaciones m谩s complejas y flexibles que las simples igualdades o desigualdades.

Si queremos saber si el d铆a es "entre semana" o es un "fin de semana" podemos escribir el siguiente c贸digo:

void main() {
final diaActual = obtenerDia(4);
print('Hoy es $diaActual'); // Entre semana
}

String obtenerDia(int dia) {
return switch (dia) {
>= 1 && <= 5 => 'Entre semana',
6 || 7 => 'Fin de semana',
_ => 'El dia no existe',
};
}

Tambi茅n podemos asignar el valor producido por la expresi贸n switch a una variable. El c贸digo anterior quedar铆a as铆:

void main() {
final dia = 5;

final diaActual = switch (dia) {
>= 1 && <= 5 => 'Entre semana',
6 || 7 => 'Fin de semana',
_ => 'El dia no existe',
};

print('Hoy es $diaActual'); // Entre semana
}

Clases selladas (sealed class)

Las clases selladas en Dart se utilizan a menudo en combinaci贸n con las expresiones switch. La estructura switch puede hacer uso exhaustivo de las subclases de una clase sellada, asegurando que se manejen todos los casos posibles.

void main() {
print('El area del circulo es: ${calcularArea(Circulo(5))}');
print('El area del cuadrado es: ${calcularArea(Cuadrado(10))}');
}

double calcularArea(Figura figura) {
return switch (figura) {
Cuadrado(lado: final lado) => lado * lado,
Circulo(radio: final radio) => 3.14 * radio * radio,
};
}

sealed class Figura {}

class Cuadrado extends Figura {
Cuadrado(this.lado);
final double lado;
}

class Circulo extends Figura {
Circulo(this.radio);
final double radio;
}

El ejemplo anterior funciona porque la clase Figura es sealed. Si no lo fuera tendr铆amos un error non_exhaustive_switch_expression

Cl谩usulas de guardia (Guard clauses)

Podemos usar la palabra reservada when en conjunto con el switch para especificar una cl谩usula de guardia. Por ejemplo, si queremos deserializar un JSON:

void main() {
var animal1Json = {
'nombre': 'Max',
'tipo': 'Gato',
};

var animal2Json = {
'nombre': 'Coco',
'tipo': 'Perro',
};

var otroJson = {
'nombre': 'Yayo',
'edad': '23',
};

print(parseJson(animal1Json)); // El gato es: Max
print(parseJson(animal2Json)); // El perro es: Coco
print(parseJson(otroJson)); // Exception: Error al Deserializar el JSON
}

Animal parseJson(Map<String, dynamic> map) {
return switch (map) {
{
'nombre': String nombre,
'tipo': String tipo,
}
when tipo == 'Gato' => Gato(nombre),
{
'nombre': String nombre,
'tipo': String tipo,
}
when tipo == 'Perro' => Perro(nombre),
_ => throw Exception('Error al Deserializar el JSON')
};
}

class Animal {
Animal(this.nombre);
final String nombre;
}

class Gato extends Animal {
Gato(String nombre) : super(nombre);


String toString() => 'El gato es: $nombre';
}

class Perro extends Animal {
Perro(String nombre) : super(nombre);


String toString() => 'El perro es: $nombre';
}

En el fragmento de c贸digo anterior tenemos tres JSON, uno es del tipo perro, otro es de tipo gato y el ultimo no tiene ningun tipo. En el switch usamos la palabra when tipo == 'Perro' o when tipo == 'Gato' para evaluar si el JSON es de tipo perro o gato y crear una instancia de sus respectivos clases Perro o Gato. Y en caso de que el JSON tenga un formato no soportado, lanzamos una excepci贸n.

Conclusi贸n

En conclusi贸n, las expresiones switch en Dart 3 ofrecen una mejora significativa sobre las estructuras de switch case tradicionales. Esta nueva versi贸n permite utilizar el switch como una expresi贸n, lo que simplifica el c贸digo y lo hace m谩s legible.

Tambi茅n se introduce la capacidad de realizar coincidencia de patrones, lo que brinda mayor flexibilidad en las comparaciones. Adem谩s, podemos hacer uso de las clases selladas en combinaci贸n con el switch, asegurando que todos los casos posibles sean manejados.

Por 煤ltimo, las cl谩usulas de guardia, utilizando la palabra reservada when, nos permiten realizar comprobaciones adicionales para deserializar JSON o manejar casos especiales.

En general, estas mejoras en las expresiones switch en Dart 3 facilitan el desarrollo de aplicaciones m谩s concisas y robustas.