Menu
CoddyTech

Múltiplos Tipos Genéricos

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

Às vezes, um único parâmetro genérico não é suficiente. E se você precisar de uma struct que contenha dois valores, e esses valores puderem ser de tipos diferentes? Rust permite usar vários parâmetros genéricos, separando-os por vírgulas.

Aqui está uma struct Pair que contém dois valores de tipos potencialmente diferentes:

struct Pair<T, U> {
    first: T,
    second: U,
}

O <T, U> declara dois parâmetros de tipo independentes. T e U podem ser do mesmo tipo ou completamente diferentes: isso depende de você ao criar uma instância:

let both_ints = Pair { first: 10, second: 20 };       // T=i32, U=i32
let mixed = Pair { first: "hello", second: 3.14 };    // T=&str, U=f64
let reversed = Pair { first: 100, second: "world" }; // T=i32, U=&str

Ao implementar métodos, você declara todos os parâmetros genéricos no bloco impl:

impl<T, U> Pair<T, U> {
    fn get_first(&self) -> &T {
        &self.first
    }

    fn get_second(&self) -> &U {
        &self.second
    }
}

Esse padrão é comum quando você precisa associar duas partes de dados relacionadas, mas potencialmente diferentes, como um par chave-valor, coordenadas com tipos numéricos diferentes ou um resultado emparelhado com metadados.

challenge icon

Desafio

Fácil

Vamos criar um sistema de armazenamento de chave-valor que demonstra o poder de vários tipos genéricos! Você criará uma struct KeyValue que pode combinar quaisquer dois tipos, perfeita para associar rótulos a dados, IDs a objetos ou qualquer outra combinação.

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

  • keyvalue.rs: Defina uma struct genérica pública chamada KeyValue<K, V> com dois campos privados: key do tipo K e value do tipo V. Implemente métodos para trabalhar com essa struct:
    • Uma função associada new que cria um KeyValue a partir de uma chave e um valor
    • Um método key que retorna uma referência à chave
    • Um método value que retorna uma referência ao valor
    • Um método set_value que substitui o valor atual por um novo
  • main.rs: Inclua seu módulo e demonstre como a mesma definição de struct funciona com diferentes combinações de tipos. Você criará pares de chave-valor com tipos mistos para mostrar a flexibilidade de vários genéricos.

No seu arquivo principal, crie e trabalhe com os seguintes pares de chave-valor:

  1. Um par com uma chave do tipo string e um valor inteiro (a primeira entrada como chave, a segunda entrada analisada como i32 como valor)
  2. Imprima a chave e o valor
  3. Atualize o valor para um novo inteiro (a terceira entrada analisada como i32)
  4. Imprima o valor atualizado
  5. Crie um segundo par com uma chave inteira e um valor do tipo string (a quarta entrada analisada como i32 como chave, a quinta entrada como valor)
  6. Imprima a chave e o valor desse par

Sua saída deve seguir este formato:

Key: {key}, Value: {value}
Updated value: {value}
Key: {key}, Value: {value}

Por exemplo, com as entradas name, 42, 100, 7 e lucky:

Key: name, Value: 42
Updated value: 100
Key: 7, Value: lucky

Observe como o primeiro par usa KeyValue<String, i32>, enquanto o segundo usa KeyValue<i32, String>: a mesma struct, diferentes combinações de tipos!

Você receberá cinco entradas: uma chave do tipo string, um valor inteiro, um inteiro de substituição, uma chave inteira e um valor do tipo string.

Experimente você mesmo

mod keyvalue;

use keyvalue::KeyValue;

fn main() {
    // Leia cinco entradas
    let mut input1 = String::new();
    std::io::stdin().read_line(&mut input1).expect("Failed to read line");
    let string_key = input1.trim().to_string();

    let mut input2 = String::new();
    std::io::stdin().read_line(&mut input2).expect("Failed to read line");
    let int_value: i32 = input2.trim().parse().expect("Failed to parse");

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

    let mut input4 = String::new();
    std::io::stdin().read_line(&mut input4).expect("Failed to read line");
    let int_key: i32 = input4.trim().parse().expect("Failed to parse");

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

    // TODO: Crie um par KeyValue<String, i32> usando string_key e int_value

    // TODO: Imprima a chave e o valor no formato: "Key: {key}, Value: {value}"

    // TODO: Atualize o valor usando set_value com replacement_int

    // TODO: Print the updated value in format: "Updated value: {value}"

    // TODO: Crie um par KeyValue<i32, String> usando int_key e string_value

    // TODO: Imprima a chave e o valor deste par no formato: "Key: {key}, Value: {value}"
}
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