🦀🔍 Se você vem do Python, enums (ou “enumerações”) podem parecer apenas uma forma elegante de definir constantes. Mas em Rust, eles são uma superpotência! Neste post, vamos explorar como os enums em Rust vão muito além do que você está acostumado no Python, permitindo associar dados, implementar métodos e usar pattern matching de forma poderosa.
Em Python, enums são principalmente usados para definir conjuntos de constantes relacionadas. Veja um exemplo básico:
from enum import Enum
class DiaDaSemana(Enum):
SEGUNDA = 1
TERCA = 2
QUARTA = 3
# ... e assim por diante
Isso é útil para organizar constantes e evitar “números mágicos” no código. Mas em Rust, os enums podem fazer muito mais!
Rust expande o conceito de enums para:
Vamos começar com o equivalente em Rust ao enum Python que vimos:
// Definindo um enum básico
enum DiaDaSemana {
Segunda,
Terca,
Quarta,
Quinta,
Sexta,
Sabado,
Domingo,
}
// Usando o enum
let hoje = DiaDaSemana::Segunda;
Até aqui, parece bem similar ao Python. Mas mesmo nesse caso simples, Rust oferece vantagens:
🚀 Aqui é onde Rust brilha! Enums podem carregar dados adicionais em cada variante. Vamos criar um enum para representar diferentes tipos de eventos em um sistema:
// Enum com dados associados
enum Evento {
Login { usuario: String, hora: String },
Logout { usuario: String },
AcessoRecurso { usuario: String, recurso: String, status: u16 },
}
// Criando instâncias
let evento1 = Evento::Login {
usuario: String::from("joao"),
hora: String::from("10:00"),
};
let evento2 = Evento::AcessoRecurso {
usuario: String::from("maria"),
recurso: String::from("/dashboard"),
status: 200,
};
Em Python, precisaríamos usar classes e herança para algo similar:
from dataclasses import dataclass
@dataclass
class Login:
usuario: str
hora: str
@dataclass
class Logout:
usuario: str
@dataclass
class AcessoRecurso:
usuario: str
recurso: str
status: int
# Uso
evento1 = Login(usuario="joao", hora="10:00")
evento2 = AcessoRecurso(usuario="maria", recurso="/dashboard", status=200)
Diferenças importantes:
EventoAssim como structs, enums em Rust podem ter métodos:
impl Evento {
fn get_usuario(&self) -> &str {
match self {
Evento::Login { usuario, .. } => usuario,
Evento::Logout { usuario } => usuario,
Evento::AcessoRecurso { usuario, .. } => usuario,
}
}
}
// Uso
println!("Usuário do evento: {}", evento1.get_usuario());
🔥 Pattern matching é onde os enums de Rust realmente brilham. Vamos comparar como lidaríamos com nosso enum Evento em Python vs Rust.
Em Python (usando if-elif e isinstance):
def processar_evento(evento):
if isinstance(evento, Login):
print(f"Usuário {evento.usuario} fez login às {evento.hora}")
elif isinstance(evento, Logout):
print(f"Usuário {evento.usuario} fez logout")
elif isinstance(evento, AcessoRecurso):
print(f"Acesso a {evento.recurso} com status {evento.status}")
else:
raise ValueError("Tipo de evento desconhecido")
Em Rust (usando match):
fn processar_evento(evento: Evento) {
match evento {
Evento::Login { usuario, hora } => {
println!("Usuário {} fez login às {}", usuario, hora);
}
Evento::Logout { usuario } => {
println!("Usuário {} fez logout", usuario);
}
Evento::AcessoRecurso { usuario, recurso, status } => {
println!("Acesso a {} com status {}", recurso, status);
}
}
}
Vantagens do pattern matching em Rust:
Vamos criar um sistema de autenticação que trata diferentes erros:
enum ErroAutenticacao {
UsuarioNaoEncontrado,
SenhaIncorreta,
ContaBloqueada,
LimiteTentativas,
}
fn tratar_erro(erro: ErroAutenticacao) -> String {
match erro {
ErroAutenticacao::UsuarioNaoEncontrado => "Usuário não cadastrado".to_string(),
ErroAutenticacao::SenhaIncorreta => "Senha incorreta".to_string(),
ErroAutenticacao::ContaBloqueada => "Conta bloqueada - contate o suporte".to_string(),
ErroAutenticacao::LimiteTentativas => "Muitas tentativas - espere 5 minutos".to_string(),
}
}
Em Python, enums são úteis para:
Em Rust, enums devem ser usados para:
💡 Dica para Pythonistas: Pense em enums Rust como uma combinação de enums Python + classes + unions types + pattern matching!
_ => {} ou trate explicitamente cada casoVamos criar um sistema que representa diferentes tipos de arquivos:
enum SistemaArquivosItem {
Arquivo {
nome: String,
tamanho: u64,
extensao: String,
},
Diretorio {
nome: String,
itens: Vec<SistemaArquivosItem>,
},
LinkSimbolico {
nome: String,
destino: String,
},
}
impl SistemaArquivosItem {
fn calcular_tamanho(&self) -> u64 {
match self {
SistemaArquivosItem::Arquivo { tamanho, .. } => *tamanho,
SistemaArquivosItem::Diretorio { itens, .. } => {
itens.iter().map(|item| item.calcular_tamanho()).sum()
}
SistemaArquivosItem::LinkSimbolico { .. } => 0,
}
}
}
// Uso
let root = SistemaArquivosItem::Diretorio {
nome: "root".to_string(),
itens: vec![
SistemaArquivosItem::Arquivo {
nome: "foto.jpg".to_string(),
tamanho: 1024,
extensao: "jpg".to_string(),
},
SistemaArquivosItem::LinkSimbolico {
nome: "atalho".to_string(),
destino: "/outro/lugar".to_string(),
},
],
};
println!("Tamanho total: {}", root.calcular_tamanho());
Enums são uma das características mais poderosas de Rust, permitindo modelar domínios complexos de forma segura e eficiente. Para Pythonistas, pode parecer estranho no começo, mas logo você vai perceber como eles tornam seu código mais expressivo e seguro.
Quer se aprofundar ainda mais em Rust? Confira nosso livro “Desbravando Rust” com muito mais conteúdo para quem vem do Python: desbravandorust.com.br