Muitas vezes é útil agrupar uma coleção de itens e tratar esses grupos como unidades. Em Rust, chamamos a esse grupo uma struct, e a cada item um dos campos da struct. Uma struct define o conjunto geral de campos disponíveis, mas um exemplo particular de uma struct chama-se instância.
Além disso, as structs podem ter métodos definidos nelas, que têm acesso aos campos. Nesse caso, a própria struct é referida como self. Quando um método usa &mut self, os campos podem ser alterados, ou mutados. Quando um método usa &self, os campos não podem ser alterados: são imutáveis. Controlar a mutabilidade ajuda o borrow-checker a garantir que classes inteiras de erros de concorrência simplesmente não acontecem em Rust.
Neste exercício, vais implementar dois tipos de métodos numa struct. Os primeiros são geralmente conhecidos como getters: expõem os campos da struct ao mundo, sem deixar que mais ninguém mute esse valor. Em Rust, estes métodos partilham idiomaticamente o nome do campo que expõem, ou seja, se tivermos um método getter que obtém um campo da struct chamado name, o método chama-‑se simplesmente name().
Também vais implementar métodos de outro tipo, geralmente conhecidos como setters. Estes alteram o valor do campo. Os setters não são muito comuns em Rust: se um campo pode ser modificado livremente, é mais comum torná-lo simplesmente público. No entanto, são úteis se a atualização do campo dever ter efeitos secundários, ou para controlo de acesso: um setter marcado como pub(crate) permite que outros módulos dentro do mesmo crate atualizem um campo privado, que não pode ser afetado pelo mundo exterior.
As structs existem em três variantes: structs com campos nomeados, structs de tupla e structs unitárias. Para este exercício de conceito, vamos explorar a primeira variante: structs com campos nomeados.
As structs são definidas usando a palavra‑chave struct, seguida do nome capitalizado do tipo que a struct descreve:
struct Item {}
Tipos adicionais são depois introduzidos no corpo da struct como campos da struct, cada um com o seu próprio tipo:
struct Item {
name: String,
weight: f32,
worth: u32,
}
Por fim, os métodos podem ser definidos nas structs dentro de um bloco impl:
impl Item {
// initializes and returns a new instance of our Item struct
fn new() -> Self {
todo!()
}
}
Com esta breve introdução à sintaxe das structs já tratada, vai em frente e dá uma olhada nas instruções deste exercício!
Estás a trabalhar na implementação de um sistema de monitorização de saúde. Como parte disso, precisas de manter registo das estatísticas de saúde dos utilizadores.
Vais começar com algumas funções esboçadas num bloco impl, bem como com a seguinte definição de struct:
pub struct User {
name: String,
age: u32,
weight: f32,
}
O teu objetivo é implementar os métodos esboçados na struct User definida no bloco impl.
Por exemplo, o método new deve devolver uma instância da struct User com os valores especificados de nome, idade e peso.
let mut bob = User::new(String::from("Bob"), 32, 155.2);
// Returns: a User with name "Bob", age 32, and weight 155.2
O método weight deve devolver o peso do User.
bob.weight();
// Returns: 155.2
O método set_age deve definir a idade do User.
bob.set_age(33);
// Updates Bob's age to 33; happy birthday Bob!
Diverte-te!
Inscreve-te no Exercism para aprenderes e dominares Rust com 99 exercícios, e mentoria humana real, tudo grátis.