Introdução
Variáveis separadas funcionam em exemplos pequenos, mas programas reais geralmente precisam manter dados relacionados juntos em um único valor. Uma struct do Rust define o formato desse registro, e um bloco impl fornece as operações que pertencem a ele.
Você completará um modelo InventoryItem preparado em quatro pequenas alterações: definir os campos, construir um item válido, calcular o valor do estoque por meio de &self e atualizar a quantidade por meio de &mut self. O programa final comprovará tanto o estado armazenado quanto o comportamento dos métodos.
Definir o registro de inventário
Nesta etapa, você definirá os três dados que pertencem a um item de inventário.
Entre no projeto Cargo preparado e abra o arquivo-fonte:
cd /home/labex/project/inventory-item
nano src/main.rs
A declaração struct InventoryItem { ... } introduz um novo tipo de registro. Dentro das chaves, cada campo tem um nome seguido de dois-pontos e do tipo correspondente. Todo valor de InventoryItem deve fornecer todos esses campos.
Substitua o comentário da Etapa 1 por estas três linhas de campos:
name: String,
price_cents: u32,
quantity: u32,
name armazena texto, enquanto os dois campos u32 armazenam números inteiros não negativos. As vírgulas finais separam os campos e facilitam a adição ou a reorganização das linhas posteriormente.
Salve com Ctrl+O, pressione Enter e saia com Ctrl+X. Peça ao Cargo para verificar as definições de tipos:
cargo check
Um resultado Finished sem avisos significa que o formato da struct é válido e que cada valor preparado tem um uso definido. O construtor ainda contém todo!, um marcador temporário para código incompleto. O Rust permite esse marcador durante cargo check, mas executar um caminho que chegue a todo! interromperia o programa com um panic. Você o substituirá antes de executar o programa na próxima etapa.
Construir um item completo
Nesta etapa, você transformará a função associada new em um construtor que retorna um InventoryItem completo.
O bloco impl InventoryItem agrupa operações relacionadas ao tipo. new é uma função associada porque não recebe self; ela é chamada por meio do tipo, usando InventoryItem::new(...). Um método como value_cents recebe self e é chamado por meio de um valor, usando item.value_cents(). O tipo de retorno Self é outro nome para InventoryItem dentro deste bloco impl.
Abra o código-fonte:
nano src/main.rs
Dentro de new, substitua a linha inteira todo!(...) por:
Self { name, price_cents, quantity }
Esta é uma expressão de struct. A abreviação de campos do Rust permite que name signifique name: name quando o parâmetro e o campo têm o mesmo nome. A expressão não tem ponto e vírgula porque é o valor retornado pela função.
Salve e saia. Em seguida, verifique e execute o programa:
cargo check
cargo run --quiet
A saída atual deve 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
Agora o item existe com os valores de campo fornecidos. Os zeros e a quantidade inalterada vêm dos dois marcadores restantes nos métodos, portanto são esperados nesta etapa.
Calcular o valor com &self
Nesta etapa, você completará um método que lê dois campos sem assumir a propriedade do item nem alterá-lo.
O parâmetro &self é uma referência compartilhada ao InventoryItem atual. Ele é uma forma abreviada de um valor emprestado cujo tipo concreto é &InventoryItem. O método recebe essa referência automaticamente quando você chama item.value_cents().
Abra o código-fonte:
nano src/main.rs
Dentro de value_cents, substitua somente o marcador 0 por:
self.price_cents * self.quantity
O ponto seleciona campos do item emprestado. A multiplicação produz o valor total em centavos, e a expressão se torna o valor u32 retornado pelo método porque não tem ponto e vírgula no final.
Salve e saia. Em seguida, execute:
cargo run --quiet
As linhas de valor agora devem ser:
Starting value: 1000 cents
...
Final value: 1000 cents
Quatro unidades a 250 centavos equivalem a 1000 centavos. As duas linhas ainda coincidem porque restock ainda não alterou a quantidade; essa alteração controlada é a etapa final.
Repor o estoque com &mut self
Nesta etapa, você completará um método que altera um campo por meio de um empréstimo exclusivo.
O receptor &mut self é uma referência mutável ao item atual. Ele permite que o método atualize campos sem assumir a propriedade do item. A variável em main já foi declarada com let mut item, portanto pode fornecer esse acesso mutável temporário.
Abra o código-fonte:
nano src/main.rs
Substitua o comentário da Etapa 4 dentro de restock por:
self.quantity += amount;
O operador += adiciona o valor à direita ao campo existente e armazena o resultado de volta nesse campo. Esta é uma instrução, por isso termina com ponto e vírgula.
Salve e saia. Em seguida, verifique e execute o modelo concluído:
cargo check
cargo run --quiet
A saída completa deve 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
A quantidade muda de quatro para sete, e o mesmo método value_cents observa o novo estado. O empréstimo mutável termina após restock, portanto o código posterior pode ler o item normalmente.
Resumo
Você definiu uma struct que mantém campos relacionados juntos, criou valores por meio de um construtor Self, leu o estado com um método &self e atualizou o estado com um método &mut self. A saída final do inventário comprovou que construção, cálculo e alteração funcionam em conjunto.


