Menu
Coddy logo textTech

Restrições Múltiplas

Parte da seção Object Oriented Programming do Journey de Rust da Coddy — lição 41 de 61.

Às vezes, um único vínculo de trait (trait bound) não é suficiente. Você pode precisar de um tipo genérico que possa tanto ser impresso e fornecer um resumo. O Rust permite que você exija múltiplos traits usando a sintaxe +.

Veja como especificar que um tipo deve implementar duas traits:

use std::fmt::Display;

trait Summary {
    fn summarize(&self) -> String;
}

fn announce<T: Display + Summary>(item: T) {
    println!("Breaking news: {}", item);
    println!("Summary: {}", item.summarize());
}

A restrição T: Display + Summary significa que "T deve implementar tanto Display quanto Summary." Dentro da função, você pode usar as capacidades de ambos os traits — imprimir com {} (de Display) e chamar summarize() (de Summary).

Você pode encadear quantos traits forem necessários:

fn process<T: Display + Summary + Clone>(item: T) {
    // Pode imprimir, resumir E clonar
}

Este padrão é essencial quando sua função depende de múltiplos comportamentos. Em vez de aceitar qualquer tipo e esperar que funcione, você declara explicitamente quais capacidades são necessárias — e o compilador as impõe em tempo de compilação.

challenge icon

Desafio

Fácil

Vamos construir um sistema de inspeção de produtos que exige que os itens tenham múltiplas capacidades! Você criará uma função genérica que aceita apenas tipos que implementam tanto uma trait personalizada quanto uma trait padrão, demonstrando como a sintaxe + combina múltiplos limites (bounds).

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

  • product.rs: Defina uma trait pública Inspectable com um método chamado inspect que recebe &self e retorna uma String contendo detalhes da inspeção. Em seguida, crie uma struct pública Gadget com os campos públicos name (String) e serial (u32). Seu Gadget deve implementar tanto Inspectable (retornando "Inspecting: {}") quanto std::fmt::Display (formatando como "{} (SN: {})"). Por fim, crie uma função genérica pública chamada full_report que aceita qualquer tipo T que implemente tanto Display quanto Inspectable. Esta função deve imprimir duas linhas: primeiro o item usando o formatador {}, e depois o resultado da chamada de inspect().
  • main.rs: Importe seu módulo product e crie uma instância de Gadget usando as entradas fornecidas. Chame full_report com seu gadget para mostrar que ele satisfaz os requisitos de ambas as traits.

O poder dos múltiplos limites é que sua função full_report pode usar capacidades de ambas as traits — exibindo o item de forma amigável E obtendo detalhes de inspeção — tudo garantido em tempo de compilação.

Sua saída deve mostrar tanto o formato de exibição quanto o resultado da inspeção:

{name} (SN: {serial})
Inspecting: {name}

Por exemplo, com as entradas Smartwatch e 98765:

Smartwatch (SN: 98765)
Inspecting: Smartwatch

Você receberá duas entradas: o nome do gadget e o número de série (analise como u32).

Folha de consulta

Você pode exigir múltiplos trait bounds em um tipo genérico usando a sintaxe +:

fn function_name<T: Trait1 + Trait2>(item: T) {
    // Pode usar capacidades de ambos os traits
}

Exemplo com Display e um trait personalizado:

use std::fmt::Display;

trait Summary {
    fn summarize(&self) -> String;
}

fn announce<T: Display + Summary>(item: T) {
    println!("Breaking news: {}", item);
    println!("Summary: {}", item.summarize());
}

Você pode encadear múltiplos traits conforme necessário:

fn process<T: Display + Summary + Clone>(item: T) {
    // Pode imprimir, resumir E clonar
}

O compilador garante que o tipo implemente todos os traits especificados em tempo de compilação.

Experimente você mesmo

mod product;

use product::{Gadget, full_report};

fn main() {
    // Ler as entradas
    let mut name = String::new();
    std::io::stdin().read_line(&mut name).expect("Failed to read line");
    let name = name.trim().to_string();
    
    let mut serial_input = String::new();
    std::io::stdin().read_line(&mut serial_input).expect("Failed to read line");
    let serial: u32 = serial_input.trim().parse().expect("Failed to parse serial");
    
    // TODO: Criar uma instância de Gadget com o nome e o serial
    
    // TODO: Chamar full_report com o seu gadget
}
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 Object Oriented Programming