Rust

Como Usar Enums em Rust: Definição, Variantes e Dados Associados em Produção

7 min de leitura

Como Usar Enums em Rust: Definição, Variantes e Dados Associados em Produção

Introdução: O Que São Enums em Rust? 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. Dominá-las é fundamental porque você as encontrará em praticamente todo código Rust profissional — desde e (enums built-in) até modelos de domínio complexos. Definição Básica e Variantes Simples Sintaxe Fundamental A definição de uma enum em Rust usa a palavra-chave seguida de um nome e um bloco contendo suas variantes: Neste exemplo simples, é uma enum com quatro variantes que não contêm dados adicionais. A forma mais comum de trabalhar com enums é usar para fazer correspondência de padrões — um mecanismo seguro

<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&lt;T&gt;</code> e <code>Result&lt;T, E&gt;</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 =&gt; println!(&quot;Seguindo para o norte!&quot;),

Direcao::Sul =&gt; println!(&quot;Seguindo para o sul!&quot;),

Direcao::Leste =&gt; println!(&quot;Seguindo para o leste!&quot;),

Direcao::Oeste =&gt; println!(&quot;Seguindo para o oeste!&quot;),

}

}</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) =&gt; {

println!(&quot;Operação bem-sucedida: {}&quot;, dados);

}

Resultado::Erro(codigo) =&gt; {

println!(&quot;Erro com código: {}&quot;, codigo);

}

Resultado::Pendente =&gt; {

println!(&quot;Ainda processando...&quot;);

}

}

}

fn main() {

let msg1 = Mensagem::Texto(&quot;Olá, mundo!&quot;.to_string());

let msg2 = Mensagem::Audio { duracao: 120, formato: &quot;MP3&quot;.to_string() };

match msg2 {

Mensagem::Texto(conteudo) =&gt; println!(&quot;Texto: {}&quot;, conteudo),

Mensagem::Audio { duracao, formato } =&gt; {

println!(&quot;Áudio de {} segundos em {}&quot;, duracao, formato);

}

Mensagem::Video { largura, altura, fps } =&gt; {

println!(&quot;Vídeo: {}x{} a {} fps&quot;, 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&lt;T&gt; e Result&lt;T, E&gt; na Prática</h3>

<p>As enums mais importantes em Rust são predefinidas na biblioteca padrão. <code>Option&lt;T&gt;</code> representa um valor que pode ou não existir, e <code>Result&lt;T, E&gt;</code> representa sucesso ou fracasso:</p>

<pre><code class="language-rust">fn dividir(a: f64, b: f64) -&gt; Result&lt;f64, String&gt; {

if b == 0.0 {

Err(&quot;Divisão por zero não permitida&quot;.to_string())

} else {

Ok(a / b)

}

}

fn buscar_usuario(id: u32) -&gt; Option&lt;String&gt; {

if id &gt; 0 &amp;&amp; id &lt;= 100 {

Some(format!(&quot;Usuário {}&quot;, id))

} else {

None

}

}

fn main() {

match dividir(10.0, 2.0) {

Ok(resultado) =&gt; println!(&quot;Resultado: {}&quot;, resultado),

Err(msg) =&gt; println!(&quot;Erro: {}&quot;, msg),

}

match buscar_usuario(42) {

Some(nome) =&gt; println!(&quot;Encontrado: {}&quot;, nome),

None =&gt; println!(&quot;Usuário não encontrado&quot;),

}

// Alternativa: métodos convenientes

let resultado = dividir(15.0, 3.0).unwrap_or(0.0);

println!(&quot;Com unwrap_or: {}&quot;, 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(&amp;self) -&gt; bool {

matches!(self, Status::Ativo)

}

fn descricao(&amp;self) -&gt; &amp;str {

match self {

Status::Ativo =&gt; &quot;Sistema operacional normalmente&quot;,

Status::Pausado =&gt; &quot;Sistema em pausa temporária&quot;,

Status::Encerrado =&gt; &quot;Sistema desligado&quot;,

}

}

}

fn main() {

let estado = Status::Ativo;

println!(&quot;Status: {}&quot;, estado.descricao());

println!(&quot;Está ativo? {}&quot;, 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&lt;T&gt;</code> e <code>Result&lt;T, E&gt;</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>

Comentários

Mais em Rust

Dominando Macros em Rust: macro_rules! e Metaprogramação em Projetos Reais
Dominando Macros em Rust: macro_rules! e Metaprogramação em Projetos Reais

Introdução às Macros em Rust Macros são uma das características mais poderosa...

O que Todo Dev Deve Saber sobre Streams Assíncronos e Concorrência Avançada com Tokio
O que Todo Dev Deve Saber sobre Streams Assíncronos e Concorrência Avançada com Tokio

Introdução ao Tokio: Fundações de Assincronismo em Rust Tokio é o runtime ass...

O que Todo Dev Deve Saber sobre Option<T> em Rust: Eliminando Null de Forma Segura
O que Todo Dev Deve Saber sobre Option<T> em Rust: Eliminando Null de Forma Segura

O Problema do Null e Por Que Rust Escolheu Option A maioria das linguagens de...