Menu
Coddy logo textTech

La clausola where

Fa parte della sezione Programmazione orientata agli oggetti del percorso Rust di Coddy. Lezione 42 di 61.

Man mano che aggiungi altri vincoli sui trait, le firme delle funzioni possono diventare difficili da leggere. Considera una funzione con più parametri generici, ognuno dei quali richiede diversi trait:

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

Funziona, ma la firma sta diventando affollata. La clausola where offre un’alternativa più pulita spostando i vincoli sui trait dopo l’elenco dei parametri:

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

Entrambe le versioni sono funzionalmente identiche: la clausola where riguarda esclusivamente la leggibilità. I requisiti di ciascun tipo compaiono su una riga a sé, così è facile scorrere quelli necessari per ogni parametro generico.

La clausola where diventa particolarmente utile quando i vincoli sono complessi o quando hai molti parametri generici. Mantiene il nome della funzione e i parametri visibili a colpo d’occhio, con i vincoli elencati separatamente sotto. Questo è lo stile preferito nella maggior parte delle basi di codice Rust quando i vincoli vanno oltre un semplice T: Trait.

challenge icon

Sfida

Facile

Costruiamo un sistema di elaborazione dei dati che usa la clausola where per mantenere leggibili i vincoli complessi sui trait! Creerai una funzione generica con più parametri di tipo, ciascuno dei quali richiede trait diversi, e organizzerai i vincoli in modo chiaro usando la sintassi where.

Organizzerai il codice in due file:

  • processor.rs: definisci due trait pubblici e una funzione generica che li usa entrambi:
    • Summarize: un trait con un metodo summary che riceve &self e restituisce una String
    • Validate: un trait con un metodo validate che riceve &self e restituisce un bool
    Poi crea una funzione generica pubblica chiamata process_items che accetta due parametri di tipi generici diversi. Usa una clausola where per specificare che il primo tipo deve implementare sia Clone sia Summarize, mentre il secondo tipo deve implementare Validate. La funzione deve stampare il riepilogo del primo elemento, quindi indicare se il secondo elemento è valido.
  • main.rs: crea due struct pubbliche che implementano i trait richiesti:
    • Article: con un campo pubblico title (String). Implementa Summarize in modo che restituisca Article: {title}, e deriva Clone.
    • Form: con un campo pubblico filled (bool). Implementa Validate in modo che restituisca il valore di filled.
    Usa gli input forniti per creare un Article e un Form, quindi chiama process_items con entrambi.

La clausola where rende la firma della funzione molto più pulita rispetto a inserire tutti i vincoli tra parentesi angolari. I requisiti di ciascun tipo appaiono su una riga separata, così è facile vedere di cosa ha bisogno ogni parametro generico.

L'output deve mostrare il riepilogo seguito dal risultato della convalida:

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

Per esempio, con gli input Rust Tips e true:

Article: Rust Tips
Valid: true

E con gli input Breaking News e false:

Article: Breaking News
Valid: false

Riceverai due input: il titolo dell'articolo e se il modulo è compilato (da analizzare come bool).

Provalo tu

mod processor;

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

// TODO: Definisci una struct pubblica Article con un campo pubblico title (String)
// Deriva Clone per Article

// TODO: Implementa Summarize per Article
// Il metodo summary deve restituire "Article: {title}"

// TODO: Definisci una struct pubblica Form con un campo pubblico filled (bool)

// TODO: Implementa Validate per Form
// Il metodo validate deve restituire il valore di 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: Crea un Article con il title fornito
    
    // TODO: Crea un Form con il valore filled fornito
    
    // TODO: Chiama process_items con article e form
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore Rust online