Menu
Coddy logo textTech

Funções Genéricas

Parte da seção Programação Orientada a Objetos do Journey de Rust da Coddy. Lição 27 de 61.

Genéricos não se limitam a structs. Você também pode escrever funções independentes que funcionam com qualquer tipo. Isso é útil quando você precisa de uma função utilitária que não pertence a uma struct específica, mas ainda deve ser flexível.

A sintaxe é semelhante à que você viu com structs. Declare o parâmetro genérico entre colchetes angulares após o nome da função e, em seguida, use-o nos parâmetros e no tipo de retorno:

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

Essa função identity recebe um valor de qualquer tipo e o retorna inalterado. <T> declara o tipo genérico, value: T o aceita como parâmetro, e -> T especifica o tipo de retorno. Quando você chama a função, Rust infere o tipo concreto:

let num = identity(42);        // T é i32
let text = identity("hello");  // T é &str

Você também pode usar vários parâmetros genéricos em funções, assim como em structs:

fn make_pair<T, U>(first: T, second: U) -> (T, U) {
    (first, second)
}

let pair = make_pair(10, "ten");  // retorna (i32, &str)

Funções genéricas permitem escrever uma lógica reutilizável uma vez e aplicá-la a muitos tipos, reduzindo a duplicação de código enquanto mantêm a segurança de tipos.

challenge icon

Desafio

Fácil

Vamos criar um módulo utilitário com funções genéricas que podem trabalhar com qualquer tipo! Você criará funções independentes que demonstram como os genéricos tornam seu código flexível e reutilizável, sem vinculá-lo a uma struct específica.

Você organizará seu código em dois arquivos:

  • utils.rs: Crie uma coleção de funções utilitárias genéricas públicas:
    • wrap_in_pair<T>: recebe um único valor e retorna uma tupla contendo esse valor duas vezes: (value, value). Isso exige que o tipo seja Clone, então use <T: Clone>
    • swap<T, U>: recebe dois valores de tipos potencialmente diferentes e retorna-os na ordem inversa como uma tupla (U, T)
  • main.rs: Importe seu módulo utilitário e demonstre essas funções genéricas funcionando com diferentes tipos. Mostre como as mesmas definições de função lidam perfeitamente com inteiros, números de ponto flutuante e strings.

No seu arquivo principal, demonstre suas funções utilitárias:

  1. Usando wrap_in_pair com um inteiro (primeira entrada, analisada como i32) e imprimindo os dois elementos
  2. Usando wrap_in_pair com uma string (segunda entrada) e imprimindo os dois elementos
  3. Usando swap com um inteiro (terceira entrada, analisada como i32) e uma string (quarta entrada), e então imprimindo o resultado trocado

Sua saída deve seguir este formato:

Pair of ints: ({value}, {value})
Pair of strings: ({value}, {value})
Swapped: ({string}, {int})

Por exemplo, com as entradas 5, hello, 42 e world:

Pair of ints: (5, 5)
Pair of strings: (hello, hello)
Swapped: (world, 42)

Observe como wrap_in_pair funciona de forma idêntica tanto para inteiros quanto para strings, e como swap lida com dois tipos completamente diferentes: essa é a flexibilidade das funções genéricas!

Você receberá quatro entradas: um inteiro, uma string, outro inteiro e outra string.

Experimente você mesmo

mod utils;

use std::io;

fn main() {
    // Leia as quatro entradas
    let mut input1 = String::new();
    io::stdin().read_line(&mut input1).expect("Failed to read line");
    let num1: i32 = input1.trim().parse().expect("Invalid integer");

    let mut input2 = String::new();
    io::stdin().read_line(&mut input2).expect("Failed to read line");
    let str1 = input2.trim().to_string();

    let mut input3 = String::new();
    io::stdin().read_line(&mut input3).expect("Failed to read line");
    let num2: i32 = input3.trim().parse().expect("Invalid integer");

    let mut input4 = String::new();
    io::stdin().read_line(&mut input4).expect("Failed to read line");
    let str2 = input4.trim().to_string();

    // TODO: Use wrap_in_pair com num1 e imprima o resultado
    // Formato: Pair of ints: ({value}, {value})

    // TODO: Use wrap_in_pair com str1 e imprima o resultado
    // Format: Pair of strings: ({value}, {value})

    // TODO: Use swap com num2 e str2, então imprima o resultado trocado
    // Formato: Swapped: ({string}, {int})
}
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 Rust online