Sobes.tech
Middle

O que são generalizações (Genéricos) em programação?

sobes.tech IA

Resposta da IA

Os genéricos são um mecanismo nas linguagens de programação que permite criar componentes (classes, interfaces, métodos/funções) que funcionam com diferentes tipos de dados, sem perder a segurança de tipos e sem recorrer a conversões de tipos (casting).

Os principais objetivos do uso de genéricos:

  • Aumento da segurança de tipos: O compilador verifica os tipos na fase de compilação, detectando erros antes da execução do programa.
  • Melhoria da legibilidade do código: É claro com quais tipos de dados o componente trabalha.
  • Reutilização de código: Pode criar um único componente que funciona com diferentes tipos, em vez de escrever várias versões.
  • Redução de conversões de tipos: Elimina a necessidade de conversões explícitas, tornando o código mais limpo e menos propenso a erros ClassCastException (em linguagens onde isso é aplicável, por exemplo, Java).

Exemplos de uso de genéricos:

  • Coleções: Listas (List), conjuntos (Set), mapas (Map) podem armazenar elementos de um tipo específico, garantindo que não sejam inseridos elementos de outro tipo.
  • Métodos/funções: Um método pode trabalhar com parâmetros ou retornar um valor de tipo universal.
  • Classes/interfaces: Pode criar estruturas de dados universais ou padrões de comportamento.

Exemplo em Java:

// Classe genérica Pair
public class Pair<T, U> {
    private T first;
    private U second;

    public Pair(T first, U second) {
        this.first = first;
        this.second = second;
    }

    public T getFirst() {
        return first;
    }

    public U getSecond() {
        return second;
    }
}

// Uso
Pair<String, Integer> pair = new Pair<>("Hello", 123);
String str = pair.getFirst(); // Sem necessidade de conversão de tipos
int num = pair.getSecond();   // Sem necessidade de conversão de tipos

// Pair<String, Integer> wrongPair = new Pair<>(123, "Hello"); // Erro de compilação: incompatibilidade de tipos

Exemplo em C#:

// Classe genérica Pair
public class Pair<T, U>
{
    public T First { get; set; }
    public U Second { get; set; }

    public Pair(T first, U second)
    {
        First = first;
        Second = second;
    }
}

// Uso
var pair = new Pair<string, int>("Hello", 123);
string str = pair.First; // Sem necessidade de conversão de tipos
int num = pair.Second;   // Sem necessidade de conversão de tipos

// var wrongPair = new Pair<string, int>(123, "Hello"); // Erro de compilação: incompatibilidade de tipos

Exemplo em TypeScript:

// Função genérica para obter o primeiro elemento de um array
function getFirstElement<T>(arr: T[]): T | undefined {
    if (arr.length > 0) {
        return arr[0];
    }
    return undefined;
}

// Uso
let numbers: number[] = [1, 2, 3];
let firstNumber = getFirstElement(numbers); // firstNumber tem tipo number

let words: string[] = ["a", "b", "c"];
let firstWord = getFirstElement(words);   // firstWord tem tipo string

// let mixedArray: (number | string)[] = [1, "a", 2];
// let firstMixed = getFirstElement(mixedArray); // firstMixed tem tipo number | string

Assim, os genéricos representam uma ferramenta poderosa para criar código flexível, seguro em tipos e reutilizável.