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:
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:
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:
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:
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
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.
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
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.
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
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>.
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