DEV Community

Toshi Ossada for flutterbrasil

Posted on

Uma nova forma de utilizar os Switch Case no Dart 3

O Dart 3 nos trouxe muitas novidades incríveis, e já abordei de algumas por aqui, um recurso muito legal foi o que denominamos de Switch Expressions.

A forma tradicional do Dart é utilizarmos o switch statement que é uma forma imperativa e procedural que estamFos acostumados.

enum MesEnum {
janeiro('Janeiro'),
fevereiro('Fevereiro'),
marco('Março'),
abril('Abril'),
maio('Maio'),
junho('Junho'),
julho('Julho'),
agosto('Agosto'),
setembro('Setembro'),
outubro('Outubro'),
novembro('Novembro'),
dezembro('Dezembro');
final String description;
const MesEnum(this.description);
}
String pegarMes(int mes) {
late String result;
switch (mes) {
case 1:
result = MesEnum.janeiro.description;
break;
case 2:
result = MesEnum.fevereiro.description;
break;
case 3:
result = MesEnum.marco.description;
break;
case 4:
result = MesEnum.abril.description;
break;
case 5:
result = MesEnum.maio.description;
break;
case 6:
result = MesEnum.junho.description;
break;
case 7:
result = MesEnum.julho.description;
break;
case 8:
result = MesEnum.agosto.description;
break;
case 9:
result = MesEnum.setembro.description;
break;
case 10:
result = MesEnum.outubro.description;
break;
case 11:
result = MesEnum.novembro.description;
break;
case 12:
result = MesEnum.dezembro.description;
break;
default:
result = 'Mês inválido';
}
return result;
}
void main() {
int mes = 1;
String result = pegarMes(mes);
print(result);
}
view raw playground.dart hosted with ❤ by GitHub

Note que, da forma antiga, com a Switch Statement não temos a capacidade de retornar diretamente o valor à variável, com a nova maneira utilizando Switch Expression traz uma importante mudança de introduzir aspectos da programação funcional para o Dart trazendo a linguagem mais flexibilidade e poder.

Um dos principais avanços das Switch Expressions no Dart 3 é a adoção de uma sintaxe similar às arrow arrow functions para mapear os cases diretamente ao valor de saída. Isso melhora a legibilidade do código e o torna menos propenso a erros.

enum MesEnum {
janeiro('Janeiro'),
fevereiro('Fevereiro'),
marco('Março'),
abril('Abril'),
maio('Maio'),
junho('Junho'),
julho('Julho'),
agosto('Agosto'),
setembro('Setembro'),
outubro('Outubro'),
novembro('Novembro'),
dezembro('Dezembro');
final String description;
const MesEnum(this.description);
}
String pegarMes(int mes) {
final result = switch (mes) {
1 => MesEnum.janeiro.description,
2 => MesEnum.fevereiro.description,
3 => MesEnum.marco.description,
4 => MesEnum.abril.description,
5 => MesEnum.maio.description,
6 => MesEnum.junho.description,
7 => MesEnum.julho.description,
8 => MesEnum.agosto.description,
9 => MesEnum.setembro.description,
10 => MesEnum.outubro.description,
11 => MesEnum.novembro.description,
12 => MesEnum.dezembro.description,
_ => 'Mês inválido', //Valor padrão, substitui o default
};
return result;
}
void main() {
int mes = 1;
String result = pegarMes(mes);
print(result);
}
view raw playground.dart hosted with ❤ by GitHub

Note que o default foi substituído apenas pelo _ (underline). Podemos melhorar ainda mais nosso código da seguinte forma:

enum MesEnum {
janeiro('Janeiro'),
fevereiro('Fevereiro'),
marco('Março'),
abril('Abril'),
maio('Maio'),
junho('Junho'),
julho('Julho'),
agosto('Agosto'),
setembro('Setembro'),
outubro('Outubro'),
novembro('Novembro'),
dezembro('Dezembro');
final String description;
const MesEnum(this.description);
}
String pegarMes(int mes) => switch (mes) {
1 => MesEnum.janeiro.description,
2 => MesEnum.fevereiro.description,
3 => MesEnum.marco.description,
4 => MesEnum.abril.description,
5 => MesEnum.maio.description,
6 => MesEnum.junho.description,
7 => MesEnum.julho.description,
8 => MesEnum.agosto.description,
9 => MesEnum.setembro.description,
10 => MesEnum.outubro.description,
11 => MesEnum.novembro.description,
12 => MesEnum.dezembro.description,
_ => 'Mês inválido', //Valor padrão, substitui o default
};
void main() {
int mes = 1;
String result = pegarMes(mes);
print(result);
}
view raw playground.dart hosted with ❤ by GitHub

Pattern Matching

Outro recurso bastante interessante é o Pattern Matching, com ele você pode desestruturar um objeto complexo ao mesmo tempo em que está validando uma condição e utilizar esses valores dentro da condição, no Dart 3 você pode utilizar o Pattern Matching dentro de suas condições switchs.

Veja no exemplo a seguir:

sealed class Funcionario {
final String nome;
Funcionario({
required this.nome,
});
double calcularPagamento();
}
class Estagiario extends Funcionario {
final double bolsaAuxilio;
Estagiario({
required super.nome,
required this.bolsaAuxilio,
});
@override
double calcularPagamento() => bolsaAuxilio;
}
class CLT extends Funcionario {
final double salario;
CLT({
required super.nome,
required this.salario,
});
double _calcularIRPF() => salario * 0.15;
@override
double calcularPagamento() => salario - _calcularIRPF();
}
void main() {
Funcionario empregado = Estagiario(nome: 'Toshi', bolsaAuxilio: 1000);
final relatorio = switch (empregado) {
(Estagiario estag) =>
'${estag.nome} Pagamento bruto: R\$${estag.bolsaAuxilio}, Pagamento Liquido: R\$${estag.calcularPagamento()}, Cargo: Estagiário',
(CLT clt) =>
'${clt.nome} Pagamento bruto: R\$${clt.salario}, Pagamento Liquido: R\$${clt.calcularPagamento()}, Cargo: CLT',
};
print(relatorio);
}
view raw playground.dart hosted with ❤ by GitHub

Guard Clauses

Como mostrei em artigos no Dart 3 temos os records, agora conseguimos usar os pattern matching em conjunto com os records, essa poderosa junção permite com que possamos desestruturar dados e executar uma condição nos dados desestruturados, utilizando a palavra reservada when para especificar a condição.

void main() {
final usuario = 'toshiossada';
final senha = '123456';
final msg = switch ((usuario, senha)) {
(String user, String password)
when user == 'toshiossada' && password == '123456' =>
'LOGIN REALIZADO COM SUCESSO',
(_, _) => 'Usuario ou senha inválidos'
};
print(msg);
}
view raw playground.dart hosted with ❤ by GitHub

Sendo que os valores também podem ser providos de uma função.

(String, String) realizarLogin() {
final usuario = 'toshiossada';
final senha = '1234564';
return (usuario, senha);
}
void main() {
final login = realizarLogin();
final msg = switch (login) {
(String user, String password)
when user == 'toshiossada' && password == '123456' =>
'LOGIN REALIZADO COM SUCESSO',
_ => 'Usuario ou senha inválidos'
};
print(msg);
}
view raw playground.dart hosted with ❤ by GitHub

Com toda certeza essas novas features deixam o Dart cada vez mais com uma cara de programação funcional, o Dart vem trazendo o que há de melhor da programação funcional e imperativa deixando o código mais legível, eficiente e testável

Image description

Entre em nosso discord para interagir com a comunidade: flutterbrasil.com.br

Sentry mobile image

Is your mobile app slow? Improve performance with these key strategies.

Improve performance with key strategies like TTID/TTFD & app start analysis.

Read the blog post

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs