Skip to content

como criar uma implementacao em rust 🦀

Published: at 21:54

Olá! vamos para mais um conteúdo de Rust?

novamente vamos iniciar o post comparando o nosso amado Rust com o typescript. Inclusive, você sabia que existe um repositório no github que serve para desenvolvedores typescript aprenderem o rust de uma forma mais fácil? clique aqui para ir até o repositório.

agora vamos ao código e a comparação em seguida:

struct Retangle {
    height: u32,
    width: u32
}

trait GeometricForm {
    fn calculate_area(&self) -> u32;
    fn new(width: u32, height: u32) -> Self;
}

impl GeometricForm for Retangle {
    fn calculate_area(&self) -> u32 {
        self.width * self.height
    }

    fn new(width: u32, height: u32) -> Self {
        Self{ width, height }
    }
}

fn main(){
    let retangle = Retangle::new(10, 20);
    let area: u32 = retangle.calculate_area();

    println!("retangle area is: {}",area);
}

inicialmente é criada uma struct que em sua definição na própria documentação é muito clara por si só.

a type that is composed of other types. (Um tipo que é composto por outros tipos).

no Rust, temos 3 tipos de struct:

struct com campos nomeados

struct User{
    pub name: String,
    pub surname: String,
    pub age: u8
}

fn main() {
    let user = User {
        name: String::from("John"),
        surname: String::from("Doe"),
        age: 77
    }
    println!("Name of the user: {}", user.name)
}

nesse código, é criada uma struct nomeada de User. Ela tem os campos nome, sobrenome e idade. Seu uso é simples como pode ser visto na função principal(main).

tuple structs (struct de tupla)

struct Log(u32, String)

fn main() {
    let log = Log(404, String::from("Page Not Found"))
    ...
}

unit-like structs (unidades como structs)

struct Electron {} // Use empty braces...
struct Proton;     // ...or just a semicolon.

fn main() {
    // Use the same notation when creating an instance.
    let x = Electron {};
    let y = Proton;
    let z = Electron; // Error
}

implementação própria da documentação das unit-like structs. Perceba que existem duas formas de criar uma unit-like struct. Tanto com chaves, quanto sem chaves. Sua implementação segue o mesmo padrão, causando erro caso haja uma implementação não coerente com a forma de declaração.

show de bola, acho que agora você já tem uma noção do que são structs e como elas funcionam no rust. A comparação com o typescript nesse caso é mais simples. Ela se parece com a estrutura type do ts.

agora vamos partir para o trait!

já o trait, parece muito uma interface! Entenda a diferença entre types e interfaces no typescript com esse vídeo do Lucas Montano. No resumo, as traits definem comportamentos e não formação de dados.

É tanto que não é possível fazer a mesma implementação do primeiro struct usando o trait, por exemplo:

//ERROR
trait User {
    name: String,
    surname: String,
    age: u8
} 

o correto nesse caso seria:

struct User {
    pub name: String,
    pub surname: String,
    pub age: u8
}

trait UserInfo {
    fn birthday(&self) -> String;
    fn full_name(&self) -> String;
    fn years_until_retirement(&self) -> u8;
}

caso, você realmente queira por algum motivo implementar formatação de dados em uma trait, o máximo que você pode fazer é isso:

trait User {
    get_name(&self) -> String;
    set_name(&mut self, value: String) -> String;
    get_surname(&self) -> String;
    set_surname(&mut self, value: String) -> String;
    get_age(&self) -> u8;
    set_age(&mut self, value: u8) -> u8;
}

isso aí! implemente getters e setters!

agora vamos para a impl. Com tudo que criamos, temos o seguinte:

struct User{
    pub name: String,
    pub surname: String,
    pub age: u8
}

trait UserInfo {
    fn birthday(&self) -> String;
    fn full_name(&self) -> String;
    fn years_until_retirement(&self) -> u8;
}

impl UserInfo for User {
    fn birthday(&self) -> String {
        format!("happy birthday, {}! you have completed {} years.", self.name, self.age)
    }
    fn full_name(&self) -> String {
        format!("{} {}", self.name, self.surname)
    }
    fn years_until_retirement(&self) -> u8 {
        65 - self.age
    }
}

o código fica extremamente intuitivo depois que entendemos realmente o conceito das coisas, não é ?!

agora vamos ao nosso último tópico:

fn new(largura: u32, altura: u32) -> Self {
    Self{ largura, altura }
}

o que essa função faz? por que ela foi nomeada como new?

no rust, exite um conceito que é a função associada. Basicamente o nosso new funciona como um constutor. Executa ao nossa implementação ser chamada. Caso necessário terão dependências que serão passadas para a criação daquela implementação.

exemplo de uso do new:

struct User {
    pub name: String,
    pub surname: String,
    pub age: u8,
}

impl User {
    fn new(name: String, surname: String, age: u8) -> Self {
        Self {
            name,
            surname,
            age,
        }
    }
}

fn main() {
    let user = User::new(String::from("John"), String::from("Doe"), 77);
    ...
}

Sabia que o Rust foi criado em 2006 por Graydon Hoare? <- esse link leva pro github dele 😉