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); | |
} |
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); | |
} |
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); | |
} |
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); | |
} |
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); | |
} |
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); | |
} |
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
Entre em nosso discord para interagir com a comunidade: flutterbrasil.com.br
Top comments (0)