Menu
Coddy logo textTech

Métodos Genéricos

Parte da seção Programação Orientada a Objetos do Journey de Dart da Coddy — lição 66 de 110.

Assim como as classes podem ser genéricas, métodos individuais também podem ter seus próprios parâmetros de tipo. Isso é útil quando você precisa de um método flexível sem tornar a classe inteira genérica.

Um método genérico declara seu parâmetro de tipo antes do tipo de retorno:

T findFirst<T>(List<T> items) {
  return items.first;
}

void main() {
  var firstNumber = findFirst<int>([1, 2, 3]);
  var firstWord = findFirst<String>(['hello', 'world']);
  
  print(firstNumber);  // 1
  print(firstWord);    // hello
}

O Dart geralmente consegue inferir o tipo a partir dos argumentos, então você nem sempre precisa especificá-lo explicitamente:

var result = findFirst([10, 20, 30]);  // Dart infers int

Métodos genéricos são particularmente úteis dentro de classes quando apenas certas operações precisam de flexibilidade de tipo:

class Printer {
  void printItem<T>(T item) {
    print('Printing: $item');
  }
  
  List<T> duplicate<T>(T item, int count) {
    return List.filled(count, item);
  }
}

void main() {
  var printer = Printer();
  printer.printItem<String>('Hello');
  printer.printItem(42);  // Tipo inferido como int
  
  var copies = printer.duplicate('Hi', 3);
  print(copies);  // [Hi, Hi, Hi]
}

Métodos genéricos oferecem um controle detalhado sobre a segurança de tipos no nível do método, mantendo suas classes mais simples enquanto ainda se beneficiam da verificação de tipos em tempo de compilação.

challenge icon

Desafio

Fácil

Vamos construir um utilitário de transformação de dados que demonstra o poder dos métodos genéricos. Você criará uma classe Transformer com métodos que podem funcionar com qualquer tipo, oferecendo flexibilidade sem tornar a classe inteira genérica.

Você organizará seu código em dois arquivos:

  • transformer.dart: Crie uma classe Transformer com estes métodos genéricos:
    • T getFirst<T>(List<T> items) - retorna o primeiro elemento de uma lista
    • T getLast<T>(List<T> items) - retorna o último elemento de uma lista
    • List<T> repeat<T>(T item, int times) - cria uma lista contendo o item repetido o número especificado de vezes
    • void printPair<A, B>(A first, B second) - imprime dois valores no formato Pair: [first] and [second]
  • main.dart: Importe seu arquivo transformer e demonstre cada método genérico com diferentes tipos:
    • Crie uma instância de Transformer
    • Use getFirst em [10, 20, 30] e imprima o resultado
    • Use getFirst em ['apple', 'banana', 'cherry'] e imprima o resultado
    • Use getLast em [1.5, 2.5, 3.5] e imprima o resultado
    • Use repeat para criar uma lista de 'Hi' repetido 4 vezes e imprima o resultado
    • Use repeat para criar uma lista de 7 repetido 3 vezes e imprima o resultado
    • Use printPair com 'Name' e 42
    • Use printPair com 100 e true

Observe como cada método declara seu(s) próprio(s) parâmetro(s) de tipo, permitindo que o mesmo objeto Transformer funcione com inteiros, strings, doubles e booleanos - tudo com total segurança de tipos. O método printPair demonstra o uso de dois parâmetros de tipo em um único método.

Saída esperada:

10
apple
3.5
[Hi, Hi, Hi, Hi]
[7, 7, 7]
Pair: Name and 42
Pair: 100 and true

Folha de consulta

Métodos genéricos declaram parâmetros de tipo antes do tipo de retorno, permitindo que métodos individuais sejam flexíveis sem tornar a classe inteira genérica:

T findFirst<T>(List<T> items) {
  return items.first;
}

O Dart pode inferir o tipo a partir dos argumentos, portanto, a especificação explícita do tipo é opcional:

var result = findFirst([10, 20, 30]);  // O Dart infere int

Métodos genéricos podem ser usados dentro de classes não genéricas:

class Printer {
  void printItem<T>(T item) {
    print('Printing: $item');
  }
  
  List<T> duplicate<T>(T item, int count) {
    return List.filled(count, item);
  }
}

Os métodos podem declarar múltiplos parâmetros de tipo:

void printPair<A, B>(A first, B second) {
  print('Pair: $first and $second');
}

Experimente você mesmo

import 'transformer.dart';

void main() {
  // Crie uma instância de Transformer
  var transformer = Transformer();

  // TODO: Use getFirst em [10, 20, 30] e imprima o resultado

  // TODO: Use getFirst em ['apple', 'banana', 'cherry'] e imprima o resultado

  // TODO: Use getLast em [1.5, 2.5, 3.5] e imprima o resultado

  // TODO: Use repeat para criar uma lista de 'Hi' repetido 4 vezes e imprima-a

  // TODO: Use repeat para criar uma lista de 7 repetido 3 vezes e imprima-a

  // TODO: Use printPair com 'Name' e 42

  // TODO: Use printPair com 100 e true
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos