Skip to main content

Separação de Propriedades e Ações | Rust

  • Separação de Propriedades e Ações | Rust

Modelo Estrutural no Rust

No Rust, a definição de dados e comportamento é separada explicitamente.

  • struct → define propriedades (estado)
  • impl → define ações (comportamento)

Essa separação não é estética. Ela é estrutural e influencia:

  • Layout de memória
  • Mutabilidade
  • Segurança
  • Extensibilidade

Definição de Propriedades (struct)

A struct define apenas o estado.

struct User {
name: String,
email: String,
active: bool,
}

Características importantes:

  • Define apenas campos
  • Não contém comportamento
  • Determina layout em memória
  • Pode ser parcialmente pública (pub por campo)

Definição de Ações (impl)

O comportamento é definido em blocos impl.

impl User {
fn new(name: String, email: String) -> Self {
Self {
name,
email,
active: true,
}
}

fn deactivate(&mut self) {
self.active = false;
}

fn is_active(&self) -> bool {
self.active
}
}

Aspectos técnicos relevantes:

  • &self → acesso imutável
  • &mut self → acesso mutável
  • self → move ownership

Essa assinatura explicita o modelo de borrowing.


Açúcar Sintático de Métodos

Internamente, métodos são funções associadas ao tipo.

user.deactivate();

Equivale a:

User::deactivate(&mut user);

Isso demonstra que:

  • Rust não possui métodos “intrínsecos”
  • Métodos são funções com um primeiro parâmetro especial

Por Que Rust Separa Estado de Comportamento

1. Controle Explícito de Mutabilidade

Mutabilidade não é implícita.

fn deactivate(&mut self)

O compilador exige que:

  • A variável seja mutável (let mut user)
  • Não haja conflitos de borrow

Isso reduz:

  • Side effects ocultos
  • Condições de corrida
  • Estados inconsistentes

2. Organização Modular

Rust permite múltiplos blocos impl.

impl User {
fn email_domain(&self) -> &str {
self.email.split('@').nth(1).unwrap()
}
}

impl User {
fn activate(&mut self) {
self.active = true;
}
}

Isso facilita:

  • Organização por domínio
  • Separação por módulos
  • Extensões sem modificar código original

Onde o trait Entra

O trait define comportamento abstrato que pode ser implementado por múltiplos tipos.

Ele não pertence à struct.

Ele descreve um contrato.

Definição de Trait

trait Identifiable {
fn id(&self) -> String;
}

Implementação para um Tipo

impl Identifiable for User {
fn id(&self) -> String {
format!("{}:{}", self.name, self.email)
}
}

Aqui ocorre algo fundamental:

  • O comportamento é separado do tipo
  • O tipo pode implementar múltiplos traits
  • Traits podem ser implementados externamente (respeitando coherence rules)

Traits vs Impl Direto

Impl Direto

impl User {
fn greet(&self) {
println!("Hello {}", self.name);
}
}
  • Método específico do tipo
  • Não é reutilizável via abstração

Trait

trait Greet {
fn greet(&self);
}

impl Greet for User {
fn greet(&self) {
println!("Hello {}", self.name);
}
}

Agora:

  • Pode ser usado como bound genérico
  • Permite polimorfismo estático
fn greet_user<T: Greet>(item: T) {
item.greet();
}

Relação com o Sistema de Tipos

Rust utiliza:

  • Tipos algébricos
  • Traits
  • Monomorfização (em generics)

Separar propriedades de ações permite:

  • Extensão por composição
  • Polimorfismo via trait bounds
  • APIs mais previsíveis

Comparação Conceitual com OOP Clássico

Linguagens OO tradicionaisRust
Classe agrupa tudoStruct define apenas dados
Métodos fazem parte da classeMétodos são funções associadas
Herança estruturalComposição + Traits
Mutabilidade implícitaMutabilidade explícita

Rust evita herança estrutural e favorece:

  • Composição
  • Implementação de múltiplos contratos
  • Segurança em tempo de compilação

Impacto em Concorrência

A separação reforça o modelo de:

  • Ownership
  • Borrow checker
  • Send e Sync (traits de concorrência)

Como mutabilidade é explícita, o compilador consegue:

  • Garantir ausência de data races
  • Impedir aliasing mutável
  • Validar acesso concorrente seguro

Fluxo Conceitual Resumido

  • struct → define estado
  • impl → define comportamento específico
  • trait → define contrato comportamental
  • impl Trait for Type → conecta contrato ao tipo

Essa arquitetura permite um modelo previsível, seguro e extensível.