Pular para o conteúdo principal
Módulo 5 · Lição 1 de 29/14 no curso~12 min
Lições do módulo (1/2)

Genéricos e Funções

Genéricos permitem escrever código flexível e reutilizável, evitando a duplicação de lógica para diferentes tipos de dados. Em vez de definir múltiplas funções ou estruturas para tipos diferentes (como i32, f64 ou String), podemos usar um parâmetro de tipo genérico, convencionalmente representado pela letra T.

O compilador Rust gerencia genéricos usando um processo chamado monomorfização: durante a compilação, ele gera uma cópia do código genérico para cada tipo concreto que é realmente usado. Isso significa que não há sobrecarga de desempenho em tempo de execução.


Funções genéricas

Para definir uma função genérica, inserimos o parâmetro de tipo <T> logo após o nome da função e antes da lista de argumentos:

Rust
fn print_value<T: std::fmt::Debug>(value: T) {
    println!("Value: {:?}", value);
}

Em funções genéricas, podemos usar o tipo genérico T para tipos de argumento e tipos de retorno:

Rust
fn identity<T>(value: T) -> T {
    value
}

Estruturas genéricas

Também podemos usar parâmetros de tipo genérico dentro de estruturas (struct) para definir campos flexíveis:

Rust
struct KeyValuePair<K, V> {
    key: K,
    value: V,
}

fn main() {
    let pair = KeyValuePair {
        key: String::from("age"),
        value: 30,
    };
}

Em um bloco impl para uma estrutura genérica, devemos declarar o parâmetro de tipo <T> imediatamente após a palavra-chave impl para indicar que estamos implementando métodos em uma estrutura genérica:

Rust
struct Container<T> {
    value: T,
}

impl<T> Container<T> {
    fn new(value: T) -> Self {
        Container { value }
    }

    fn value(&self) -> &T {
        &self.value
    }
}

Experimente você mesmo

Exercício 1: A estrutura de pontos

Exercício#rust.m5.l1.e1
Tentativas: 0Carregando…

Defina uma estrutura genérica chamada Point<T> com dois campos: x do tipo T e y do tipo T. Na função principal, instancie uma variável point contendo um Point com valores inteiros x = 5 e y = 10 e, em seguida, imprima o valor de point.x.

Carregando editor…
Mostrar dica

Declare a estrutura usando `struct Point<T> { x: T, y: T }`. Instancie-o em main e use `point.x` para imprimi-lo.

Solução disponível após 3 tentativas

Exercício 2: Revertendo uma Tupla com troca

Exercício#rust.m5.l1.e2
Tentativas: 0Carregando…

Escreva uma função genérica chamada swap<T> que aceita uma tupla de dois elementos (T, T) e retorna uma nova tupla (T, T) com suas posições invertidas. Na função principal, chame a função com tupla (1, 2) e imprima o resultado.

Carregando editor…
Mostrar dica

A assinatura da função deve ser `fn swap<T>(pair: (T, T)) -> (T, T)`. Retorne a tupla invertida com `(pair.1, pair.0)`.

Solução disponível após 3 tentativas

Exercício 3: A estrutura do contêiner

Exercício#rust.m5.l1.e3
Tentativas: 0Carregando…

Defina uma estrutura genérica Container<T> contendo um campo de valor do tipo T. Implemente um bloco impl genérico para definir um novo método que aceite um valor do tipo T e retorne uma instância de Container<T>.

Carregando editor…
Mostrar dica

Use `impl<T> Container<T>`para implementar o método associado`fn new(value: T) -> Self { Container { value } }`.

Solução disponível após 3 tentativas