Structs
Struct no modo mais simples de se falar é uma estrutura de valores em "uma única variável". Não consigo pensar em um modo mais fácil de explicar com palavras o que seria uma "struct", sua declaração é simples ela segue o seguinte padrão struct Nome { campos }
.
#![allow(unused)] fn main() { struct Cliente { nome: String, ano_de_nascimento: u16, documento: String, } }
O modo de declaração dos campos/atributos de uma struct lembra bastante o de um json, para criarmos uma variável de uma struct podemos fazer da seguinte maneira:
struct Cliente { nome: String, ano_de_nascimento: u16, documento: String, } //--declaração da estrutura Cliente fn main() { let cliente: Cliente = Cliente { nome: String::from("Paulo"), ano_de_nascimento: 1999, documento: String::from("Onde?") }; }
Podemos acessar os campos da variável utilizando apenas um ".nome_do_campo".
struct Cliente { nome: String, ano_de_nascimento: u16, documento: String, } //--declaração da estrutura Cliente fn main() { let cliente = Cliente { nome: String::from("Paulo"), ano_de_nascimento: 1999, documento: String::from("Onde?") }; println!("Nome do cliente: {}", cliente.nome); }
Declarando comportamento para uma Struct
Em Rust uma struct pode ter funções associadas a ela, essas funções são chamadas de métodos, aqui temos uma das características de Programação Orientada a Objetos no Rust, como a linguagem é de multi-paradigmas temos alguns recursos desse modo de programação disponível.
Para implementarmos métodos para a struct Cliente
utilizamos a palavra reservada impl
seguida do nome da estrutura impl Cliente { implementações }
, vamos começar com a implementação de um método estático para nos auxiliar na criação de variáveis do tipo Cliente
.
struct Cliente { nome: String, ano_de_nascimento: u16, documento: String, } impl Cliente { fn new(nome: String, ano_de_nascimento: u16, documento: String) -> Self { Self { nome: nome, ano_de_nascimento, /* Como o atributo tem o mesmo nome do parâmetro/variável eu não preciso colocar o padrão chave:valor */ documento } } } fn main() { let cliente = Cliente::new(String::from("Paulo"), 1999, String::from("Onde?")); println!("Nome do cliente: {}", cliente.nome); }
A palavra Self
com 'S' maiúsculo é um modo de falar que estamos se referindo a própria struct que esta sendo implementada.
Temos também métodos que dependem de uma instância da struct, para este tipo de métodos utilizamos a própria struct utilizando a palavra self
com 's' minúsculo como parâmetro do método, pode ser uma referência mutável, imutável ou pode não ser referência, porém, não sendo uma referência perdemos o ownership da struct e sua memória é liberada.
struct Cliente { nome: String, ano_de_nascimento: u16, documento: String, } impl Cliente { fn new(nome: String, ano_de_nascimento: u16, documento: String) -> Self { Self { nome: nome, ano_de_nascimento, /* Como o atributo tem o mesmo nome do parâmetro/variável eu não preciso colocar o padrão chave:valor */ documento } } fn diz_oi(&self) { println!("{} disse oi", self.nome); } fn diz_tchau(self) { println!("{} disse tchau e foi embora", self.nome); } fn mudar_nome(&mut self, novo_nome: String) { //para utilizar este método a instância de //cliente deve ser mutável self.nome = novo_nome; } } fn main() { let mut cliente = Cliente::new(String::from("Paulo"), 1999, String::from("Onde?")); cliente.diz_oi(); cliente.mudar_nome(String::from("Novo nome")); cliente.diz_oi(); cliente.diz_tchau(); //a partir daqui a memória deste //cliente foi liberada não conseguimos mais utilizar }
Caso tentarmos utilizar a instância de cliente após a chamada do método diz_tchau
teremos o seguinte erro
--> main.rs:42:5
|
37 | let mut cliente = Cliente::new(String::from("Paulo"), 1999, String::from("Onde?"));
| ----------- move occurs because `cliente` has type `Cliente`, which does not implement the `Copy` trait
...
41 | cliente.diz_tchau(); //a partir daqui a memória deste
| ----------- `cliente` moved due to this method call
42 | cliente.diz_oi(); //cliente foi liberada não conseguimos mais utilizar
| ^^^^^^^ value borrowed here after move
|
note: this function takes ownership of the receiver `self`, which moves `cliente`
--> main.rs:25:18
|
25 | fn diz_tchau(self) {
| ^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0382`.