Menu
Coddy logo textTech

A Cláusula Where

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

À medida que você adiciona mais limites de traits, as assinaturas de funções podem se tornar difíceis de ler. Considere uma função com vários parâmetros genéricos, cada um exigindo várias traits:

fn complex_operation<T: Display + Clone, U: Debug + Summary>(first: T, second: U) {
    // ...
}

Isso funciona, mas a assinatura está ficando sobrecarregada. A cláusula where oferece uma alternativa mais limpa, movendo os limites de traits para depois da lista de parâmetros:

fn complex_operation<T, U>(first: T, second: U)
where
    T: Display + Clone,
    U: Debug + Summary,
{
    // ...
}

Ambas as versões são funcionalmente idênticas: a cláusula where diz respeito apenas à legibilidade. Os requisitos de cada tipo aparecem em sua própria linha, facilitando verificar o que cada parâmetro genérico precisa.

A cláusula where torna-se especialmente valiosa quando os limites são complexos ou quando você tem muitos parâmetros genéricos. Ela mantém o nome e os parâmetros da função visíveis rapidamente, com as restrições listadas separadamente abaixo. Esse é o estilo preferido na maioria das bases de código Rust quando os limites vão além de um simples T: Trait.

challenge icon

Desafio

Fácil

Vamos construir um sistema de processamento de dados que usa a cláusula where para manter limites complexos de traits legíveis! Você criará uma função genérica com vários parâmetros de tipo, cada um exigindo traits diferentes, e organizará os limites de forma clara usando a sintaxe where.

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

  • processor.rs: Defina duas traits públicas e uma função genérica que use ambas:
    • Summarize: uma trait com um método summary que recebe &self e retorna uma String
    • Validate: uma trait com um método validate que recebe &self e retorna um bool
    Em seguida, crie uma função genérica pública chamada process_items que aceite dois parâmetros de tipos genéricos diferentes. Use uma cláusula where para especificar que o primeiro tipo deve implementar tanto Clone quanto Summarize, enquanto o segundo tipo deve implementar Validate. A função deve imprimir o resumo do primeiro item e, em seguida, imprimir se o segundo item é válido.
  • main.rs: Crie duas structs públicas que implementem as traits necessárias:
    • Article: com um campo público title (String). Implemente Summarize para retornar Article: {title} e derive Clone.
    • Form: com um campo público filled (bool). Implemente Validate para retornar o valor de filled.
    Use as entradas fornecidas para criar um Article e um Form e, em seguida, chame process_items com ambos.

A cláusula where torna a assinatura da sua função muito mais limpa do que colocar todos os limites entre os sinais de menor e maior. Os requisitos de cada tipo aparecem em sua própria linha, facilitando a visualização do que cada parâmetro genérico precisa.

Sua saída deve mostrar o resumo seguido do resultado da validação:

Article: {title}
Valid: {true/false}

Por exemplo, com as entradas Rust Tips e true:

Article: Rust Tips
Valid: true

E com as entradas Breaking News e false:

Article: Breaking News
Valid: false

Você receberá duas entradas: o título do artigo e se o formulário está preenchido (faça o parsing como bool).

Experimente você mesmo

mod processor;

use processor::{Summarize, Validate, process_items};
use std::io;

// TODO: Defina uma struct pública Article com um campo público title (String)
// Derive Clone para Article

// TODO: Implemente Summarize para Article
// O método summary deve retornar "Article: {title}"

// TODO: Defina uma struct pública Form com um campo público filled (bool)

// TODO: Implemente Validate para Form
// O método validate deve retornar o valor de filled

fn main() {
    let mut title = String::new();
    io::stdin().read_line(&mut title).expect("Failed to read line");
    let title = title.trim().to_string();

    let mut filled_input = String::new();
    io::stdin().read_line(&mut filled_input).expect("Failed to read line");
    let filled: bool = filled_input.trim().parse().expect("Failed to parse bool");

    // TODO: Crie um Article com o title fornecido
    
    // TODO: Crie um Form com o valor filled fornecido
    
    // TODO: Chame process_items com o article e form
}
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