Menu
Coddy logo textTech

Métodos genéricos

Parte de la sección Programación Orientada a Objetos del Journey de Dart de Coddy — lección 66 de 110.

Al igual que las clases pueden ser genéricas, los métodos individuales también pueden tener sus propios parámetros de tipo. Esto es útil cuando necesitas un método flexible sin hacer que toda la clase sea genérica.

Un método genérico declara su parámetro de tipo antes del 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
}

Dart a menudo puede inferir el tipo a partir de los argumentos, por lo que no siempre es necesario especificarlo explícitamente:

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

Los métodos genéricos son particularmente útiles dentro de las clases cuando solo ciertas operaciones necesitan flexibilidad de tipos:

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]
}

Los métodos genéricos te brindan un control detallado sobre la seguridad de tipos a nivel de método, manteniendo tus clases más simples mientras sigues beneficiándote de la comprobación de tipos en tiempo de compilación.

challenge icon

Desafío

Fácil

Vamos a construir una utilidad de transformación de datos que muestre el poder de los métodos genéricos. Crearás una clase Transformer con métodos que pueden trabajar con cualquier tipo, dándote flexibilidad sin hacer que toda la clase sea genérica.

Organizarás tu código en dos archivos:

  • transformer.dart: Crea una clase Transformer con estos métodos genéricos:
    • T getFirst<T>(List<T> items) - devuelve el primer elemento de una lista
    • T getLast<T>(List<T> items) - devuelve el último elemento de una lista
    • List<T> repeat<T>(T item, int times) - crea una lista que contiene el elemento repetido el número especificado de veces
    • void printPair<A, B>(A first, B second) - imprime dos valores en el formato Pair: [first] and [second]
  • main.dart: Importa tu archivo transformer y demuestra cada método genérico con diferentes tipos:
    • Crea una instancia de Transformer
    • Usa getFirst en [10, 20, 30] e imprime el resultado
    • Usa getFirst en ['apple', 'banana', 'cherry'] e imprime el resultado
    • Usa getLast en [1.5, 2.5, 3.5] e imprime el resultado
    • Usa repeat para crear una lista de 'Hi' repetido 4 veces e imprime el resultado
    • Usa repeat para crear una lista de 7 repetido 3 veces e imprime el resultado
    • Usa printPair con 'Name' y 42
    • Usa printPair con 100 y true

Observa cómo cada método declara su(s) propio(s) parámetro(s) de tipo, permitiendo que el mismo objeto Transformer trabaje con enteros, cadenas, dobles y booleanos, todo con total seguridad de tipos. El método printPair demuestra el uso de dos parámetros de tipo en un solo método.

Resultado esperado:

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

Hoja de referencia

Los métodos genéricos declaran parámetros de tipo antes del tipo de retorno, lo que permite que los métodos individuales sean flexibles sin que toda la clase sea genérica:

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

Dart puede inferir el tipo a partir de los argumentos, por lo que la especificación explícita del tipo es opcional:

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

Los métodos genéricos se pueden utilizar dentro de clases no 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);
  }
}

Los métodos pueden declarar múltiples parámetros de tipo:

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

Pruébalo tú mismo

import 'transformer.dart';

void main() {
  // Crea una instancia de Transformer
  var transformer = Transformer();

  // TODO: Usa getFirst en [10, 20, 30] e imprime el resultado

  // TODO: Usa getFirst en ['apple', 'banana', 'cherry'] e imprime el resultado

  // TODO: Usa getLast en [1.5, 2.5, 3.5] e imprime el resultado

  // TODO: Usa repeat para crear una lista de 'Hi' repetido 4 veces e imprímela

  // TODO: Usa repeat para crear una lista de 7 repetido 3 veces e imprímela

  // TODO: Usa printPair con 'Name' y 42

  // TODO: Usa printPair con 100 y true
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos