Recursos Avançados
Generics
Generics permitem criar código reutilizável que funciona com diferentes tipos:
class Caixa<T> {
T conteudo;
Caixa(this.conteudo);
T obter() {
return conteudo;
}
}
var caixaString = Caixa<String>("Olá");
var caixaInt = Caixa<int>(42);
print(caixaString.obter()); // "Olá"
print(caixaInt.obter()); // 42
Com funções:
T primeiro<T>(List<T> lista) {
return lista[0];
}
String nome = primeiro<String>(['João', 'Maria']);
int numero = primeiro<int>([1, 2, 3]);
Typedefs
Typedefs criam aliases (apelidos) para tipos de função:
typedef Operacao = int Function(int, int);
int somar(int a, int b) => a + b;
int multiplicar(int a, int b) => a * b;
void executar(Operacao op, int a, int b) {
print(op(a, b));
}
executar(somar, 5, 3); // 8
executar(multiplicar, 4, 2); // 8
Exercícios
-
Generics em classes: Crie uma classe genérica
Pilha<T>que armazene elementos em uma lista. Implemente métodosempilhar,desempilharetopo. Teste com diferentes tipos (String, int). -
Generics em funções: Crie uma função genérica
trocarque receba uma lista e dois índices, e troque os elementos nessas posições. A função deve funcionar com qualquer tipo. -
Typedefs: Crie um typedef
Comparadorpara funções que comparam dois números. Crie funções que encontrem o maior e menor número em uma lista usando esse comparador. -
Generics com restrições: Crie uma classe genérica
Caixaque só aceite tipos numéricos (int ou double). Adicione um método que some todos os valores. -
Generics aninhados: Crie uma função genérica que receba uma lista de listas e retorne uma lista "achatada" (flatten) de qualquer tipo.
Soluções
Ver solução do exercício 1
class Pilha<T> {
List<T> _elementos = [];
void empilhar(T elemento) {
_elementos.add(elemento);
}
T? desempilhar() {
if (_elementos.isEmpty) {
return null;
}
return _elementos.removeLast();
}
T? topo() {
if (_elementos.isEmpty) {
return null;
}
return _elementos.last;
}
bool get vazia => _elementos.isEmpty;
int get tamanho => _elementos.length;
}
void main() {
var pilhaString = Pilha<String>();
pilhaString.empilhar("primeiro");
pilhaString.empilhar("segundo");
print(pilhaString.topo()); // segundo
print(pilhaString.desempilhar()); // segundo
var pilhaInt = Pilha<int>();
pilhaInt.empilhar(1);
pilhaInt.empilhar(2);
pilhaInt.empilhar(3);
print(pilhaInt.topo()); // 3
}
Ver solução do exercício 2
void trocar<T>(List<T> lista, int indice1, int indice2) {
if (indice1 >= 0 && indice1 < lista.length &&
indice2 >= 0 && indice2 < lista.length) {
T temp = lista[indice1];
lista[indice1] = lista[indice2];
lista[indice2] = temp;
}
}
void main() {
List<int> numeros = [1, 2, 3, 4, 5];
trocar(numeros, 0, 4);
print(numeros); // [5, 2, 3, 4, 1]
List<String> palavras = ["a", "b", "c"];
trocar(palavras, 0, 2);
print(palavras); // [c, b, a]
}
Ver solução do exercício 3
typedef Comparador = int Function(int, int);
int compararMaior(int a, int b) => a.compareTo(b);
int compararMenor(int a, int b) => b.compareTo(a);
int? encontrar(List<int> numeros, Comparador comparador) {
if (numeros.isEmpty) return null;
int resultado = numeros[0];
for (int num in numeros) {
if (comparador(num, resultado) > 0) {
resultado = num;
}
}
return resultado;
}
void main() {
List<int> numeros = [3, 1, 4, 1, 5, 9, 2, 6];
int? maior = encontrar(numeros, compararMaior);
print("Maior: $maior"); // 9
int? menor = encontrar(numeros, compararMenor);
print("Menor: $menor"); // 1
}
Ver solução do exercício 4
class Caixa<T extends num> {
List<T> valores = [];
void adicionar(T valor) {
valores.add(valor);
}
num somar() {
num soma = 0;
for (T valor in valores) {
soma += valor;
}
return soma;
}
}
void main() {
var caixaInt = Caixa<int>();
caixaInt.adicionar(10);
caixaInt.adicionar(20);
caixaInt.adicionar(30);
print(caixaInt.somar()); // 60
var caixaDouble = Caixa<double>();
caixaDouble.adicionar(1.5);
caixaDouble.adicionar(2.5);
print(caixaDouble.somar()); // 4.0
}
Ver solução do exercício 5
List<T> achatar<T>(List<List<T>> listas) {
List<T> resultado = [];
for (List<T> lista in listas) {
resultado.addAll(lista);
}
return resultado;
}
void main() {
List<List<int>> numeros = [
[1, 2, 3],
[4, 5],
[6, 7, 8, 9]
];
List<int> achatado = achatar(numeros);
print(achatado); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
List<List<String>> palavras = [
["a", "b"],
["c", "d", "e"]
];
List<String> palavrasAchatadas = achatar(palavras);
print(palavrasAchatadas); // [a, b, c, d, e]
}