Menu
Coddy logo textTech

Classes Genéricas

Parte da seção Programação Orientada a Objetos do Journey de Java da Coddy. Lição 54 de 87.

Agora que você entende por que os genéricos são úteis, vamos criar sua própria classe genérica. Uma classe genérica declara um ou mais parâmetros de tipo entre colchetes angulares após o nome da classe, que podem então ser usados em toda a classe.

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

O T é um parâmetro de tipo: um espaço reservado que é substituído por um tipo real quando você cria uma instância. Você pode usar qualquer nome, mas letras maiúsculas únicas são convencionais: T para Type, E para Element, K para Key, V para Value.

Ao instanciar uma classe genérica, você especifica o tipo real entre colchetes angulares:

Box<String> stringBox = new Box<>();
stringBox.set("Hello");
String value = stringBox.get();  // Não é necessário casting

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

Observe o <> (operador diamante) no lado direito: Java infere o tipo a partir da declaração. Você também pode usar vários parâmetros de tipo para classes que precisam trabalhar com mais de um 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

Desafio

Fácil

Vamos criar um sistema de registro de presentes que demonstra o poder das classes genéricas. Você criará um sistema de armazenamento flexível que pode conter qualquer tipo de item de presente, além de um registro que associa nomes de presentes aos seus detalhes usando vários parâmetros de tipo.

Você organizará seu código em três arquivos:

  • GiftBox.java: crie uma classe genérica que possa envolver qualquer tipo de presente. Sua GiftBox<T> deve ter um campo privado item do tipo T e um campo privado wrapped (booleano) que começa como false. Inclua um construtor que aceite o item, um método getItem() que retorne o item, um método wrap() que defina wrapped como true e um método isWrapped() que retorne o status de wrapped. Adicione um método getStatus() que retorne [item] (wrapped) ou [item] (unwrapped), dependendo do estado de wrapped.
  • Registry.java: crie uma classe genérica com dois parâmetros de tipo que associe um destinatário ao seu presente. Sua Registry<K, V> deve ter campos privados recipient do tipo K e gift do tipo V. Inclua um construtor que aceite ambos os valores, métodos getter getRecipient() e getGift(), e um método getEntry() que retorne: [recipient] -> [gift]
  • Main.java: dê vida ao seu registro de presentes! Você receberá três entradas: o nome do destinatário (String), a descrição do presente (String) e o valor do presente (inteiro que representa dólares).

    Primeiro, crie uma GiftBox<String> contendo a descrição do presente. Envolva-a usando o método wrap() e, em seguida, imprima seu status.

    Depois, crie uma GiftBox<Integer> contendo o valor do presente (representando o valor de um cartão-presente). Não envolva esta: imprima seu status para mostrar que ela está desembrulhada.

    Por fim, crie uma Registry<String, String> associando o nome do destinatário à descrição do presente e imprima a entrada do registro.

Você receberá três entradas, nesta ordem: nome do destinatário, descrição do presente e valor do presente (como um inteiro).

Observe como a mesma classe GiftBox funciona perfeitamente tanto com os tipos String quanto com Integer: essa é a beleza dos genéricos! E a classe Registry demonstra como vários parâmetros de tipo permitem criar associações flexíveis entre quaisquer dois tipos.

Experimente você mesmo

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Ler entradas
        String recipientName = scanner.nextLine();
        String giftDescription = scanner.nextLine();
        int giftValue = scanner.nextInt();
        
        // TODO: Criar um GiftBox<String> contendo a descrição do presente
        // TODO: Embrulhá-lo usando o método wrap()
        // TODO: Imprimir seu status usando getStatus()
        
        // TODO: Criar um GiftBox<Integer> contendo o valor do presente
        // TODO: Não embrulhe este - imprima seu status (deve mostrar desembrulhado)
        
        // TODO: Criar um Registry<String, String> pareando o destinatário com a descrição do presente
        // TODO: Imprimir a entrada do registro usando getEntry()
    }
}
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

Pratique por conta própria: Compilador de Java online