Múltiples Bloques de Implementación
Parte de la sección Object Oriented Programming del Journey de Rust de Coddy — lección 5 de 61.
Rust permite dividir los métodos de un struct en múltiples bloques impl. Aunque todo podría ir en un solo bloque, separarlos puede hacer que tu código sea más organizado y legible.
Aquí hay un struct con su funcionalidad dividida en dos bloques de implementación:
struct BankAccount {
balance: f64,
}
// Constructor y consultas básicas
impl BankAccount {
fn new(initial: f64) -> BankAccount {
BankAccount { balance: initial }
}
fn balance(&self) -> f64 {
self.balance
}
}
// Métodos de transacción
impl BankAccount {
fn deposit(&mut self, amount: f64) {
self.balance += amount;
}
fn withdraw(&mut self, amount: f64) {
self.balance -= amount;
}
}
Ambos bloques funcionan juntos a la perfección; Rust los trata como si fueran uno solo. Puedes llamar a cualquier método independientemente del bloque en el que esté definido:
fn main() {
let mut account = BankAccount::new(100.0);
account.deposit(50.0);
println!("{}", account.balance()); // 150
}
Este patrón se vuelve especialmente útil a medida que tus structs crecen. Podrías agrupar los constructores, mantener los métodos de solo lectura separados de los que mutan, u organizarlos por funcionalidad. No hay límite en cuanto a cuántos bloques impl puede tener una struct.
Desafío
FácilCrea una estructura Player con dos campos: name (String) y score (u32).
Organiza los métodos de la estructura en dos bloques de implementación separados:
Primer bloque impl — Constructor y consulta:
new— una función asociada que toma unname: Stringy devuelve unPlayerconscoreestablecido en0get_score— toma&selfy devuelve la puntuación actual comou32
Segundo bloque impl — Modificaciones de puntuación:
add_points— toma&mut selfypoints: u32, y suma los puntos a la puntuaciónreset_score— toma&mut selfy restablece la puntuación a0
Recibirás tres entradas:
- Primera línea: el nombre del jugador (String)
- Segunda línea: puntos a añadir en la primera ronda (u32)
- Tercera línea: puntos a añadir en la segunda ronda (u32)
Crea un jugador usando Player::new, añade los puntos de la primera ronda, imprime la puntuación, luego restablece la puntuación, añade los puntos de la segunda ronda e imprime la puntuación final.
Formato de salida esperado:
{score_after_first_round}
{score_after_reset_and_second_round}Hoja de referencia
Rust permite dividir los métodos de una estructura en múltiples bloques impl para una mejor organización:
struct BankAccount {
balance: f64,
}
// First impl block
impl BankAccount {
fn new(initial: f64) -> BankAccount {
BankAccount { balance: initial }
}
fn balance(&self) -> f64 {
self.balance
}
}
// Second impl block
impl BankAccount {
fn deposit(&mut self, amount: f64) {
self.balance += amount;
}
fn withdraw(&mut self, amount: f64) {
self.balance -= amount;
}
}
Todos los métodos de los diferentes bloques impl funcionan juntos a la perfección:
let mut account = BankAccount::new(100.0);
account.deposit(50.0);
println!("{}", account.balance()); // 150
No hay límite en la cantidad de bloques impl que puede tener una estructura. Este patrón es útil para agrupar funcionalidades relacionadas, como separar los constructores de los métodos de mutación.
Pruébalo tú mismo
use std::io;
// TODO: Definir la estructura Player con los campos name (String) y score (u32)
// TODO: Primer bloque impl - Constructor y métodos de consulta (new, get_score)
// TODO: Segundo bloque impl - Métodos de modificación de puntuación (add_points, reset_score)
fn main() {
let mut input = String::new();
// Leer el nombre del jugador
io::stdin().read_line(&mut input).expect("Failed to read line");
let name = input.trim().to_string();
// Leer los puntos de la primera ronda
input.clear();
io::stdin().read_line(&mut input).expect("Failed to read line");
let first_round: u32 = input.trim().parse().expect("Invalid number");
// Leer los puntos de la segunda ronda
input.clear();
io::stdin().read_line(&mut input).expect("Failed to read line");
let second_round: u32 = input.trim().parse().expect("Invalid number");
// TODO: Crear un jugador usando Player::new
// TODO: Añadir los puntos de la primera ronda e imprimir la puntuación
// TODO: Reiniciar la puntuación
// TODO: Añadir los puntos de la segunda ronda e imprimir la puntuación final
}Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Object Oriented Programming
1Métodos y Comportamiento
Intro a Bloques de ImplementaciónEl Parámetro SelfMétodos MutablesFunciones AsociadasMúltiples Bloques de ImplementaciónEncadenamiento de MétodosResumen - Acciones de Rectángulo4Proyecto: Mascota virtual
Definir la mascotaAlimentar a la mascota7Traits estándar
El trait DebugEl trait DisplayClone y CopyTraits de igualdadResumen - Punto imprimible10Proyecto: Sistema de documentos
El Trait DrawComponente de texto2Encapsulamiento y módulos
Conceptos básicos de módulosLa palabra clave PublicCampos privadosGettersSettersRepaso - Casillero seguro5Genéricos
Estructuras genéricasMétodos genéricosMúltiples tipos genéricosFunciones genéricasResumen - Punto de coordenadas8Traits como límites
Sintaxis de límites de traitsLímites múltiplesLa cláusula whereRetornar tipos con traitsResumen: Impresora genérica11Patrones de diseño en Rust
Patrón NewtypeComposiciónEl Trait DropFrom e IntoResumen - Mock de Smart Pointer3Enums avanzados
Enums con datosMétodos en EnumsCoincidencia de variantes de datosEl Enum Option revisitadoResumen - Enum Shape6Definición de Traits
¿Qué es un Trait?Implementación de TraitsImplementaciones por defectoSobrescribir valores por defectoTraits con parámetrosResumen - Reproductor multimedia