
Cleuton Sampaio - Me siga aqui. RustingCrab Repo.
Considere o seguinte código Rust:
// Usamos a instrução "use" para importar uma função ou tipo específico de outro módulo
use std::cmp::max;
/// Estrutura que representa uma pessoa
struct Pessoa {
nome: String,
idade: u8,
}
impl Pessoa {
/// Método associado que cria uma nova Pessoa
fn new(nome: String, idade: u8) -> Self {
Pessoa { nome, idade }
}
/// Método que verifica se a pessoa é maior de idade
fn maior_de_idade(&self) -> bool {
self.idade >= 18
}
/// Método que retorna uma saudação personalizada
fn saudacao(&self) -> String {
format!("Olá, meu nome é {} e eu tenho {} anos.", self.nome, self.idade)
}
}
/// Função simples que calcula o maior de dois números
fn maior_numero(a: i32, b: i32) -> i32 {
max(a, b)
}
/// Função principal do programa
fn main() {
// Criando variáveis simples
let x = 10;
let y = 20;
// Chamando a função maior_numero
let maior = maior_numero(x, y);
println!("O maior número entre {} e {} é {}.", x, y, maior);
// Criando uma instância de Pessoa
let pessoa = Pessoa::new(String::from("Fulano"), 25);
// Usando os métodos da estrutura Pessoa
println!("{}", pessoa.saudacao());
if pessoa.maior_de_idade() {
println!("{} é maior de idade.", pessoa.nome);
} else {
println!("{} não é maior de idade.", pessoa.nome);
}
// Usando uma macro (println!) para imprimir uma mensagem
println!("Este é um exemplo de programa Rust!");
}
Perguntas:
use?Pessoa?impl Pessoa {} faz?fn new ..?fn maior_de_idade? Qual é a diferença para fn new?Self (com maiúscula) e self (com minúscula). Qual é a diferença?u8 e i32?Essas perguntas você deve estar fazendo se é uma pessoa observadora. Vamos procurar responder aqui.
use?No código fornecido, a instrução use std::cmp::max; importa a função max do módulo std::cmp para o escopo atual. Isso permite que a função max seja utilizada diretamente como max(a, b) sem a necessidade de referenciá-la completamente como std::cmp::max(a, b) cada vez que for chamada.
O uso da instrução use torna o código mais limpo e legível, evitando repetições desnecessárias de caminhos completos. Embora não seja estritamente obrigatório usar use—já que você poderia chamar std::cmp::max diretamente—a prática de importar funções ou tipos frequentemente utilizados é recomendada para simplificar e organizar melhor o código.
Pessoa?Pessoa é uma struct. Em Rust, uma struct é o equivalente a uma classe, podendo ter propriedades e métodos. Mas lembre-se que a implementação de orientação a objetos em Rust é simplificada, de maneira semelhante ao que ocorre em Go (Golang), portanto, struct não é uma classe, embora pareça muito com uma.
No exemplo, cada instância da struct pessoa tem 2 propriedades e dois métodos:
nome.idade.maior_de_idade().saudacao().E podemos criar instâncias da struct Pessoa invocando a função new():
let pessoa = Pessoa::new(String::from("Fulano"), 25);
impl Pessoa {} faz?A declaração impl Pessoa { ... } cria um bloco de implementação para a estrutura Pessoa. Dentro desse bloco, você pode definir métodos associados a Pessoa, sejam eles métodos que operam em uma instância específica (acessando seus campos via &self), métodos de classe (associados ao tipo, chamados via Pessoa::metodo()), ou funções auxiliares relacionadas ao tipo.
Resumindo, o impl permite adicionar comportamento (funções e métodos) ao tipo definido anteriormente (struct Pessoa).
fn new ..?fn new(...) é um método associado, comumente utilizado em Rust como um “construtor” de uma determinada estrutura (struct). Ele não é um construtor no sentido tradicional de linguagens orientadas a objetos, mas sim uma função estática (associada ao tipo) que cria e retorna uma nova instância do tipo definido. Esse padrão fornece uma maneira simples de inicializar os campos de uma struct e configurar qualquer lógica necessária antes de entregar a instância pronta para uso.
Ele não é um método de uma instância de
Pessoa, é uma função associada à struct Pessoa.
fn maior_de_idade? Qual é a diferença para fn new?fn maior_de_idade é um método de instância da struct Pessoa que verifica se uma pessoa tem 18 anos ou mais, retornando true se for maior de idade e false caso contrário. Ele utiliza &self, o que significa que opera sobre uma instância já existente de Pessoa.
A diferença para fn new é que new é um método associado (estático) ao tipo Pessoa, usado para criar e retornar uma nova instância dessa struct. Enquanto maior_de_idade depende de uma instância existente para funcionar, new não precisa de uma instância prévia e é chamado diretamente a partir do tipo (Pessoa::new(...)).
Self (com maiúscula) e self (com minúscula). Qual é a diferença?Self (com “S” maiúsculo) se refere ao próprio tipo dentro do bloco impl. Por exemplo, em impl Pessoa, Self é equivalente a Pessoa. Você usa Self em métodos associados para indicar que a função retorna ou lida com o tipo em si, sem estar ligada a nenhuma instância específica.
Já self (com “s” minúsculo) é usado como o primeiro parâmetro dos métodos de instância (como fn maior_de_idade(&self)) e se refere a uma instância específica do tipo. Dessa forma, self dá acesso aos campos e métodos do objeto atual em que a função está sendo chamada.
Quando um método ou função é chamado utilizando ::, estamos acessando métodos associados ao tipo, também chamados de métodos estáticos. Esses métodos não precisam de uma instância para serem invocados; eles se referem diretamente à definição do tipo. Por exemplo, Pessoa::new(...) cria uma nova instância da struct Pessoa sem precisar de uma instância prévia.
Já quando usamos o operador ., estamos chamando um método em uma instância já existente de um tipo. Nesse caso, o método recebe automaticamente uma referência para o objeto atual através do parâmetro self (normalmente &self), permitindo acessar seus campos e comportamentos particulares. Por exemplo, pessoa.maior_de_idade() chama o método maior_de_idade em uma instância específica de Pessoa.
u8 e i32?u8 é um tipo de dado inteiro sem sinal com tamanho de 8 bits, representando valores de 0 a 255. Já i32 é um tipo de dado inteiro com sinal de 32 bits, capaz de representar valores tanto negativos quanto positivos, indo de -2.147.483.648 até 2.147.483.647. Em resumo, u8 só aceita números não negativos e ocupa menos espaço, enquanto i32 pode lidar com uma faixa muito maior de valores, incluindo números negativos.