<h2>Introdução: O Que São Enums em Rust?</h2>
<p>Enums (enumerações) são um dos pilares do sistema de tipos de Rust, permitindo definir um tipo que pode assumir múltiplos valores nomeados distintos. Diferentemente de linguagens como C ou Java, enums em Rust são muito mais poderosos: cada variante pode conter dados associados de qualquer tipo. Isso torna as enums ideais para representar estados, padrões discriminados e estruturas de dados heterogêneas com segurança de tipo garantida em tempo de compilação.</p>
<p>Dominá-las é fundamental porque você as encontrará em praticamente todo código Rust profissional — desde <code>Option<T></code> e <code>Result<T, E></code> (enums built-in) até modelos de domínio complexos.</p>
<h2>Definição Básica e Variantes Simples</h2>
<h3>Sintaxe Fundamental</h3>
<p>A definição de uma enum em Rust usa a palavra-chave <code>enum</code> seguida de um nome e um bloco contendo suas variantes:</p>
<pre><code class="language-rust">enum Direcao {
Norte,
Sul,
Leste,
Oeste,
}
fn main() {
let meu_caminho = Direcao::Norte;
// As variantes são acessadas com a sintaxe NomeDaEnum::Variante
match meu_caminho {
Direcao::Norte => println!("Seguindo para o norte!"),
Direcao::Sul => println!("Seguindo para o sul!"),
Direcao::Leste => println!("Seguindo para o leste!"),
Direcao::Oeste => println!("Seguindo para o oeste!"),
}
}</code></pre>
<p>Neste exemplo simples, <code>Direcao</code> é uma enum com quatro variantes que não contêm dados adicionais. A forma mais comum de trabalhar com enums é usar <code>match</code> para fazer correspondência de padrões — um mecanismo seguro e exaustivo que força você a tratar todas as variantes possíveis.</p>
<h3>Variantes e Namespacing</h3>
<p>Cada variante é automaticamente um construtor do tipo. Você pode importar uma variante específica para evitar repetir o prefixo <code>Direcao::</code>:</p>
<pre><code class="language-rust">use Direcao::*;
let sentido = Leste; // Funciona sem prefixo após use</code></pre>
<h2>Dados Associados e Variantes Heterogêneas</h2>
<h3>Armazenando Dados nas Variantes</h3>
<p>A verdadeira força das enums em Rust emerge quando você associa dados às variantes. Cada variante pode ter um tipo diferente e quantidade diferente de dados:</p>
<pre><code class="language-rust">enum Resultado {
Sucesso(String), // Variante com String
Erro(u32), // Variante com código de erro (u32)
Pendente, // Sem dados associados
}
enum Mensagem {
Texto(String),
Audio { duracao: u32, formato: String },
Video { largura: u32, altura: u32, fps: u32 },
}
fn processar_resultado(res: Resultado) {
match res {
Resultado::Sucesso(dados) => {
println!("Operação bem-sucedida: {}", dados);
}
Resultado::Erro(codigo) => {
println!("Erro com código: {}", codigo);
}
Resultado::Pendente => {
println!("Ainda processando...");
}
}
}
fn main() {
let msg1 = Mensagem::Texto("Olá, mundo!".to_string());
let msg2 = Mensagem::Audio { duracao: 120, formato: "MP3".to_string() };
match msg2 {
Mensagem::Texto(conteudo) => println!("Texto: {}", conteudo),
Mensagem::Audio { duracao, formato } => {
println!("Áudio de {} segundos em {}", duracao, formato);
}
Mensagem::Video { largura, altura, fps } => {
println!("Vídeo: {}x{} a {} fps", largura, altura, fps);
}
}
}</code></pre>
<p>Observe que você pode usar dados nomeados (struct-like) ou dados posicionais (tuple-like) nas variantes. O compilador rastreia cada variante e seus tipos, prevenindo acessos indevidos em tempo de compilação.</p>
<h3>Option<T> e Result<T, E> na Prática</h3>
<p>As enums mais importantes em Rust são predefinidas na biblioteca padrão. <code>Option<T></code> representa um valor que pode ou não existir, e <code>Result<T, E></code> representa sucesso ou fracasso:</p>
<pre><code class="language-rust">fn dividir(a: f64, b: f64) -> Result<f64, String> {
if b == 0.0 {
Err("Divisão por zero não permitida".to_string())
} else {
Ok(a / b)
}
}
fn buscar_usuario(id: u32) -> Option<String> {
if id > 0 && id <= 100 {
Some(format!("Usuário {}", id))
} else {
None
}
}
fn main() {
match dividir(10.0, 2.0) {
Ok(resultado) => println!("Resultado: {}", resultado),
Err(msg) => println!("Erro: {}", msg),
}
match buscar_usuario(42) {
Some(nome) => println!("Encontrado: {}", nome),
None => println!("Usuário não encontrado"),
}
// Alternativa: métodos convenientes
let resultado = dividir(15.0, 3.0).unwrap_or(0.0);
println!("Com unwrap_or: {}", resultado);
}</code></pre>
<h2>Implementando Métodos em Enums</h2>
<p>Assim como structs, enums podem ter métodos implementados via blocos <code>impl</code>:</p>
<pre><code class="language-rust">enum Status {
Ativo,
Pausado,
Encerrado,
}
impl Status {
fn eh_ativo(&self) -> bool {
matches!(self, Status::Ativo)
}
fn descricao(&self) -> &str {
match self {
Status::Ativo => "Sistema operacional normalmente",
Status::Pausado => "Sistema em pausa temporária",
Status::Encerrado => "Sistema desligado",
}
}
}
fn main() {
let estado = Status::Ativo;
println!("Status: {}", estado.descricao());
println!("Está ativo? {}", estado.eh_ativo());
}</code></pre>
<p>Este padrão é especialmente útil para adicionar comportamento e lógica de negócio diretamente às suas enums, mantendo o código organizado e orientado a objetos de forma idiomática em Rust.</p>
<h2>Conclusão</h2>
<p>Nesta aula, aprendemos que <strong>enums em Rust são tipos discriminados que podem armazenar dados heterogêneos</strong> de forma segura e que o compilador valida todas as possibilidades em tempo de compilação. <strong>O pattern matching via <code>match</code> é a forma idiomática de trabalhar com enums</strong>, forçando você a considerar todos os casos. Por fim, <strong><code>Option<T></code> e <code>Result<T, E></code> são enums especiais usadas para tratamento de ausência de dados e erros</strong>, substituindo adequadamente valores nulos e exceções tradicionais.</p>
<h2>Referências</h2>
<ul>
<li><a href="https://doc.rust-lang.org/book/ch06-00-enums.html" target="_blank" rel="noopener noreferrer">The Rust Programming Language - Enums</a></li>
<li><a href="https://doc.rust-lang.org/rust-by-example/custom_types/enum.html" target="_blank" rel="noopener noreferrer">Rust by Example - Enums</a></li>
<li><a href="https://doc.rust-lang.org/std/option/" target="_blank" rel="noopener noreferrer">Standard Library: Option and Result</a></li>
<li><a href="https://rust-lang.github.io/rfcs/2005-match-ergonomics.html" target="_blank" rel="noopener noreferrer">Rust RFC 2005 - Match Ergonomics</a></li>
<li><a href="https://github.com/google/comprehensive-rust" target="_blank" rel="noopener noreferrer">Comprehensive Rust Course - Enums</a></li>
</ul>