Introducción
Las variables independientes funcionan en ejemplos pequeños, pero los programas reales suelen necesitar un único valor que mantenga juntos los datos relacionados. Un struct de Rust define la estructura de ese registro, y un bloque impl proporciona las operaciones que pertenecen a dicho registro.
Completará un modelo InventoryItem preparado mediante cuatro modificaciones pequeñas: definirá sus campos, construirá un elemento válido, calculará su valor de inventario mediante &self y actualizará su cantidad mediante &mut self. El programa final demostrará tanto el estado almacenado como el comportamiento de los métodos.
Definir el registro de inventario
En este paso, definirá las tres piezas de datos que pertenecen a un elemento de inventario.
Entre en el proyecto de Cargo preparado y abra su archivo fuente:
cd /home/labex/project/inventory-item
nano src/main.rs
La declaración struct InventoryItem { ... } introduce un nuevo tipo de registro. Dentro de las llaves, cada campo tiene un nombre seguido de dos puntos y su tipo. Cada valor de InventoryItem debe proporcionar todos estos campos.
Reemplace el comentario del paso 1 por estas tres líneas de campos:
name: String,
price_cents: u32,
quantity: u32,
name es propietario del texto, mientras que los dos campos u32 almacenan números enteros no negativos. Las comas finales separan los campos y facilitan añadir o reordenar líneas más adelante.
Guarde con Ctrl+O, presione Enter y salga con Ctrl+X. Pida a Cargo que compruebe las definiciones de tipos:
cargo check
Un resultado Finished sin advertencias significa que la estructura del struct es válida y que cada valor preparado tiene un uso claro. El constructor todavía contiene todo!, una marca temporal para indicar código sin terminar. Rust la permite durante cargo check, pero ejecutar una ruta que llegue a todo! terminaría con un panic. La reemplazará antes de ejecutar el programa en el siguiente paso.
Construir un elemento completo
En este paso, convertirá la función asociada new en un constructor que devuelva un InventoryItem completo.
El bloque impl InventoryItem agrupa las operaciones relacionadas con el tipo. new es una función asociada porque no recibe self; se invoca mediante el tipo con InventoryItem::new(...). Un método como value_cents recibe self y se invoca mediante un valor con item.value_cents(). El tipo de retorno Self es otro nombre para InventoryItem dentro de este bloque impl.
Abra el código fuente:
nano src/main.rs
Dentro de new, reemplace toda la línea todo!(...) por:
Self { name, price_cents, quantity }
Esta es una expresión de struct. La abreviatura de campos de Rust permite que name signifique name: name cuando el parámetro y el campo tienen el mismo nombre. La expresión no lleva punto y coma porque es el valor que devuelve la función.
Guarde y salga; después, compruebe y ejecute el programa:
cargo check
cargo run --quiet
La salida actual debe ser:
Preparing Notebook at 250 cents with 4 units
Item: Notebook
Unit price: 250 cents
Starting value: 0 cents
Adding 3 units
Quantity after restock: 4
Final value: 0 cents
El elemento ya existe con los valores de campo proporcionados. Los ceros y la cantidad sin cambios proceden de los dos marcadores de posición restantes en los métodos, por lo que son esperables en esta etapa.
Calcular el valor con &self
En este paso, completará un método que lee dos campos sin tomar la propiedad del elemento ni modificarlo.
El parámetro &self es una referencia compartida al InventoryItem actual. Es una forma abreviada de un valor prestado cuyo tipo concreto es &InventoryItem. El método recibe esta referencia automáticamente cuando llama a item.value_cents().
Abra el código fuente:
nano src/main.rs
Dentro de value_cents, reemplace únicamente el marcador de posición 0 por:
self.price_cents * self.quantity
El punto permite seleccionar campos del elemento prestado. La multiplicación produce el valor total en centavos, y la expresión se convierte en el valor u32 que devuelve el método porque no tiene un punto y coma final.
Guarde y salga; después, ejecute:
cargo run --quiet
Las líneas del valor deben mostrar ahora:
Starting value: 1000 cents
...
Final value: 1000 cents
Cuatro unidades a 250 centavos equivalen a 1000 centavos. Ambas líneas siguen coincidiendo porque restock todavía no ha cambiado la cantidad; esa modificación controlada es el último paso.
Reponer existencias con &mut self
En este paso, completará un método que cambia un campo mediante un acceso prestado exclusivo.
El receptor &mut self es una referencia mutable al elemento actual. Permite que el método actualice campos sin tomar la propiedad del elemento. La variable en main ya está declarada con let mut item, por lo que puede proporcionar ese acceso mutable temporal.
Abra el código fuente:
nano src/main.rs
Reemplace el comentario del paso 4 dentro de restock por:
self.quantity += amount;
El operador += suma el valor de la derecha al campo existente y vuelve a guardar el resultado en ese campo. Esta es una instrucción, por lo que termina con un punto y coma.
Guarde y salga; después, compruebe y ejecute el modelo terminado:
cargo check
cargo run --quiet
La salida completa debe ser:
Preparing Notebook at 250 cents with 4 units
Item: Notebook
Unit price: 250 cents
Starting value: 1000 cents
Adding 3 units
Quantity after restock: 7
Final value: 1750 cents
La cantidad cambia de cuatro a siete, y el mismo método value_cents observa el nuevo estado. El préstamo mutable termina después de restock, por lo que el código posterior puede leer el elemento con normalidad.
Resumen
Definió un struct que mantiene juntos los campos relacionados, construyó valores mediante un constructor Self, leyó el estado con un método &self y actualizó el estado con un método &mut self. La salida final del inventario demostró que la construcción, el cálculo y la modificación funcionan conjuntamente.


