Menu
Coddy logo textTech

Traits con parámetros

Parte de la sección Object Oriented Programming del Journey de Rust de Coddy — lección 33 de 61.

Hasta ahora, nuestros métodos de trait solo han tomado &self como parámetro. Pero los métodos de trait pueden aceptar parámetros adicionales al igual que los métodos regulares; esto los hace mucho más útiles para operaciones del mundo real.

Al definir un trait, puedes incluir cualquier parámetro que necesites en las firmas de los métodos:

trait Calculator {
    fn add(&self, a: i32, b: i32) -> i32;
    fn multiply(&self, a: i32, b: i32) -> i32;
}

Este trait Calculator requiere dos métodos, cada uno de los cuales acepta dos enteros además de &self. Cualquier tipo que implemente este trait debe proporcionar ambas operaciones con estas firmas exactas.

Así es como un struct podría implementarlo:

struct BasicCalc;

impl Calculator for BasicCalc {
    fn add(&self, a: i32, b: i32) -> i32 {
        a + b
    }
    
    fn multiply(&self, a: i32, b: i32) -> i32 {
        a * b
    }
}

Ahora puedes usar estos métodos con argumentos:

let calc = BasicCalc;
println!("{}", calc.add(5, 3));       // 8
println!("{}", calc.multiply(4, 7));  // 28

El trait define qué parámetros acepta cada método, mientras que la implementación define cómo se utilizan esos parámetros. Esto permite que diferentes tipos realicen las mismas operaciones a su propia manera; tal vez un LoggingCalc podría imprimir cada operación antes de devolver el resultado.

challenge icon

Desafío

Fácil

¡Vamos a construir un conjunto de herramientas de manipulación de cadenas donde diferentes procesadores puedan transformar texto a su manera! Crearás un trait TextProcessor con métodos que aceptan parámetros y luego lo implementarás para dos tipos de procesadores diferentes.

Organizarás tu código en tres archivos:

  • processor.rs: Define un trait público TextProcessor con dos métodos que aceptan parámetros:
    • repeat(&self, text: &str, times: u32) -> String — repite el texto dado un número especificado de veces
    • truncate(&self, text: &str, max_len: usize) -> String — acorta el texto a la longitud máxima especificada
  • processors.rs: Crea dos structs públicos que implementen tu trait:
    • SimpleProcessor — un struct de unidad que repite el texto con espacios entre cada repetición (por ejemplo, "Hi" repetido 3 veces se convierte en "Hi Hi Hi") y trunca simplemente cortando en la longitud máxima
    • FancyProcessor — un struct de unidad que repite el texto con " * " entre repeticiones (por ejemplo, "Hi" repetido 3 veces se convierte en "Hi * Hi * Hi") y trunca añadiendo "..." si el texto fue acortado (solo si el texto original era más largo que max_len)
  • main.rs: Une tus módulos y demuestra cómo los mismos métodos del trait producen resultados diferentes según el procesador que utilices.

En tu archivo principal, crea ambos procesadores y utiliza las entradas para probarlos. Recibirás tres entradas: una cadena de texto, un recuento de repeticiones y una longitud máxima.

Imprime cuatro líneas que muestren el comportamiento de cada procesador:

Simple repeat: {result}
Simple truncate: {result}
Fancy repeat: {result}
Fancy truncate: {result}

Por ejemplo, con las entradas Hello, 3, y 4:

Simple repeat: Hello Hello Hello
Simple truncate: Hell
Fancy repeat: Hello * Hello * Hello
Fancy truncate: Hell...

Observa cómo ambos procesadores cumplen con el mismo contrato TextProcessor, pero cada uno transforma el texto a su manera única. El trait define qué parámetros aceptan los métodos, mientras que cada implementación decide cómo usarlos.

Recibirás tres entradas: el texto a procesar, el número de repeticiones (analizar como u32) y la longitud máxima para el truncamiento (analizar como usize).

Hoja de referencia

Los métodos de los traits pueden aceptar parámetros adicionales más allá de &self:

trait Calculator {
    fn add(&self, a: i32, b: i32) -> i32;
    fn multiply(&self, a: i32, b: i32) -> i32;
}

Implementando un trait con parámetros:

struct BasicCalc;

impl Calculator for BasicCalc {
    fn add(&self, a: i32, b: i32) -> i32 {
        a + b
    }
    
    fn multiply(&self, a: i32, b: i32) -> i32 {
        a * b
    }
}

Usando métodos de trait con argumentos:

let calc = BasicCalc;
println!("{}", calc.add(5, 3));       // 8
println!("{}", calc.multiply(4, 7));  // 28

El trait define qué parámetros acepta cada método, mientras que la implementación define cómo se utilizan esos parámetros.

Pruébalo tú mismo

mod processor;
mod processors;

use processor::TextProcessor;
use processors::{SimpleProcessor, FancyProcessor};

fn main() {
    // Leer entradas
    let mut text = String::new();
    std::io::stdin().read_line(&mut text).expect("Failed to read line");
    let text = text.trim();
    
    let mut times_input = String::new();
    std::io::stdin().read_line(&mut times_input).expect("Failed to read line");
    let times: u32 = times_input.trim().parse().expect("Failed to parse times");
    
    let mut max_len_input = String::new();
    std::io::stdin().read_line(&mut max_len_input).expect("Failed to read line");
    let max_len: usize = max_len_input.trim().parse().expect("Failed to parse max_len");
    
    // Crear procesadores
    let simple = SimpleProcessor;
    let fancy = FancyProcessor;
    
    // TODO: Usar los procesadores para transformar el texto e imprimir los resultados
    // Imprimir cuatro líneas:
    // Simple repeat: {result}
    // Simple truncate: {result}
    // Fancy repeat: {result}
    // Fancy truncate: {result}
}
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 Object Oriented Programming