Menu
Coddy logo textTech

La cláusula where

Parte de la sección Programación Orientada a Objetos del Journey de Rust de Coddy. Lección 42 de 61.

A medida que añades más restricciones de traits, las firmas de las funciones pueden volverse difíciles de leer. Considera una función con varios parámetros genéricos, cada uno de los cuales requiere varios traits:

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

Esto funciona, pero la firma se está volviendo demasiado cargada. La cláusula where ofrece una alternativa más limpia al mover los límites de los traits después de la lista de parámetros:

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

Ambas versiones son funcionalmente idénticas: la cláusula where se refiere únicamente a la legibilidad. Los requisitos de cada tipo aparecen en su propia línea, lo que facilita revisar lo que necesita cada parámetro genérico.

La cláusula where resulta especialmente valiosa cuando las restricciones son complejas o cuando tienes muchos parámetros genéricos. Mantiene el nombre y los parámetros de la función visibles de un vistazo, con las restricciones enumeradas por separado a continuación. Este es el estilo preferido en la mayoría de las bases de código de Rust cuando las restricciones van más allá de un simple T: Trait.

challenge icon

Desafío

Fácil

¡Construyamos un sistema de procesamiento de datos que use la cláusula where para mantener legibles los límites de traits complejos! Crearás una función genérica con varios parámetros de tipo, cada uno de los cuales requiere distintos traits, y organizarás los límites claramente mediante la sintaxis where.

Organizarás tu código en dos archivos:

  • processor.rs: Define dos traits públicos y una función genérica que use ambos:
    • Summarize: un trait con un método summary que toma &self y devuelve un String
    • Validate: un trait con un método validate que toma &self y devuelve un bool
    Después, crea una función genérica pública llamada process_items que acepte dos parámetros de tipos genéricos diferentes. Usa una cláusula where para especificar que el primer tipo debe implementar tanto Clone como Summarize, mientras que el segundo tipo debe implementar Validate. La función debe imprimir el resumen del primer elemento y después imprimir si el segundo elemento es válido.
  • main.rs: Crea dos structs públicos que implementen los traits requeridos:
    • Article: con un campo público title (String). Implementa Summarize para devolver Article: {title} y deriva Clone.
    • Form: con un campo público filled (bool). Implementa Validate para devolver el valor de filled.
    Usa las entradas proporcionadas para crear un Article y un Form, y después llama a process_items con ambos.

La cláusula where hace que la firma de tu función sea mucho más limpia que si incluyeras todos los límites entre los corchetes angulares. Los requisitos de cada tipo aparecen en su propia línea, lo que facilita ver qué necesita cada parámetro genérico.

Tu salida debe mostrar el resumen seguido del resultado de la validación:

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

Por ejemplo, con las entradas Rust Tips y true:

Article: Rust Tips
Valid: true

Y con las entradas Breaking News y false:

Article: Breaking News
Valid: false

Recibirás dos entradas: el título del artículo y si el formulario está rellenado (parsea como bool).

Pruébalo tú mismo

mod processor;

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

// TODO: Define una struct pública Article con un campo público title (String)
// Deriva Clone para Article

// TODO: Implementa Summarize para Article
// El método summary debe devolver "Article: {title}"

// TODO: Define una struct pública Form con un campo público filled (bool)

// TODO: Implementa Validate para Form
// El método validate debe devolver el 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: Crea un Article con el title dado
    
    // TODO: Crea un Form con el valor filled dado
    
    // TODO: Llama a process_items con el article y form
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos

Practica por tu cuenta: Compilador de Rust online