Menu
Coddy logo textTech

Clases genéricas

Parte de la sección Programación Orientada a Objetos del Journey de Java de Coddy — lección 54 de 87.

Ahora que entiendes por qué los genéricos son útiles, vamos a crear tu propia clase genérica. Una clase genérica declara uno o más parámetros de tipo entre corchetes angulares después del nombre de la clase, los cuales pueden utilizarse en toda la clase.

class Box<T> {
    private T content;
    
    public void set(T content) {
        this.content = content;
    }
    
    public T get() {
        return content;
    }
}

El T es un parámetro de tipo: un marcador de posición que se reemplaza por un tipo real cuando creas una instancia. Puedes usar cualquier nombre, pero las letras mayúsculas individuales son convencionales: T para Tipo, E para Elemento, K para Clave, V para Valor.

Al instanciar una clase genérica, se especifica el tipo real entre paréntesis angulares:

Box<String> stringBox = new Box<>();
stringBox.set("Hello");
String value = stringBox.get();  // No casting needed

Box<Integer> intBox = new Box<>();
intBox.set(42);
Integer num = intBox.get();

Observa el <> (operador diamante) en el lado derecho: Java infiere el tipo a partir de la declaración. También puedes usar múltiples parámetros de tipo para clases que necesiten trabajar con más de un tipo:

class Pair<K, V> {
    private K key;
    private V value;
    
    public Pair(K key, V value) {
        this.key = key;
        this.value = value;
    }
    
    public K getKey() { return key; }
    public V getValue() { return value; }
}

Pair<String, Integer> pair = new Pair<>("age", 25);
challenge icon

Desafío

Fácil

Vamos a construir un sistema de registro de regalos que demuestre el poder de las clases genéricas. Crearás un sistema de almacenamiento flexible que puede contener cualquier tipo de artículo de regalo, además de un registro que empareja los nombres de los regalos con sus detalles utilizando múltiples parámetros de tipo.

Organizarás tu código en tres archivos:

  • GiftBox.java: Crea una clase genérica que pueda envolver cualquier tipo de regalo. Tu GiftBox<T> debe tener un campo privado item de tipo T y un campo privado wrapped (boolean) que comience como false. Incluye un constructor que acepte el artículo, un método getItem() que devuelva el artículo, un método wrap() que establezca wrapped a true, y un método isWrapped() que devuelva el estado de envoltura. Añade un método getStatus() que devuelva ya sea [item] (wrapped) o [item] (unwrapped) dependiendo del estado de envoltura.
  • Registry.java: Crea una clase genérica con dos parámetros de tipo que empareje a un destinatario con su regalo. Tu Registry<K, V> debe tener campos privados recipient de tipo K y gift de tipo V. Incluye un constructor que acepte ambos valores, métodos getter getRecipient() y getGift(), y un método getEntry() que devuelva: [recipient] -> [gift]
  • Main.java: ¡Dale vida a tu registro de regalos! Recibirás tres entradas: un nombre de destinatario (String), una descripción del regalo (String) y un valor del regalo (entero que representa dólares).

    Primero, crea un GiftBox<String> que contenga la descripción del regalo. Envuélvelo usando el método wrap(), luego imprime su estado.

    A continuación, crea un GiftBox<Integer> que contenga el valor del regalo (que representa el monto de una tarjeta de regalo). No envuelvas este; imprime su estado para mostrar que está unwrapped.

    Finalmente, crea un Registry<String, String> emparejando el nombre del destinatario con la descripción del regalo, e imprime la entrada del registro.

Recibirás tres entradas en orden: nombre del destinatario, descripción del regalo y valor del regalo (como un entero).

Observa cómo la misma clase GiftBox funciona perfectamente tanto con tipos String como Integer; ¡esa es la belleza de los genéricos! Y la clase Registry demuestra cómo los múltiples parámetros de tipo te permiten crear emparejamientos flexibles entre dos tipos cualesquiera.

Hoja de referencia

Una clase genérica declara uno o más parámetros de tipo entre corchetes angulares después del nombre de la clase, los cuales pueden utilizarse en toda la clase:

class Box<T> {
    private T content;
    
    public void set(T content) {
        this.content = content;
    }
    
    public T get() {
        return content;
    }
}

La T es un parámetro de tipo: un marcador de posición que se reemplaza por un tipo real al crear una instancia. Las convenciones comunes utilizan letras mayúsculas individuales: T para Type (Tipo), E para Element (Elemento), K para Key (Clave), V para Value (Valor).

Al instanciar una clase genérica, especifique el tipo real entre corchetes angulares:

Box<String> stringBox = new Box<>();
stringBox.set("Hello");
String value = stringBox.get();  // No casting needed

Box<Integer> intBox = new Box<>();
intBox.set(42);
Integer num = intBox.get();

El <> (operador diamante) permite que Java infiera el tipo a partir de la declaración.

Utilice múltiples parámetros de tipo para clases que trabajan con más de un tipo:

class Pair<K, V> {
    private K key;
    private V value;
    
    public Pair(K key, V value) {
        this.key = key;
        this.value = value;
    }
    
    public K getKey() { return key; }
    public V getValue() { return value; }
}

Pair<String, Integer> pair = new Pair<>("age", 25);

Pruébalo tú mismo

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Lee las entradas
        String recipientName = scanner.nextLine();
        String giftDescription = scanner.nextLine();
        int giftValue = scanner.nextInt();
        
        // TODO: Crea un GiftBox<String> que contenga la descripción del regalo (giftDescription)
        // TODO: Envuélvelo usando el método wrap()
        // TODO: Imprime su estado usando getStatus()
        
        // TODO: Crea un GiftBox<Integer> que contenga el valor del regalo (giftValue)
        // TODO: No envuelvas este - imprime su estado (debería mostrarse como no envuelto)
        
        // TODO: Crea un Registry<String, String> emparejando al destinatario con la descripción del regalo
        // TODO: Imprime la entrada del registro usando getEntry()
    }
}
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