<h2>Introdução: O que são Traits?</h2>
<p>Traits em Rust são abstrações poderosas que permitem definir comportamentos compartilhados entre tipos diferentes. Eles funcionam como "contratos" que especificam quais métodos um tipo deve implementar. Diferente de herança tradicional em linguagens orientadas a objetos, traits fornecem composição de comportamento de forma segura e explícita, aproveitando o sistema de tipos de Rust para garantir segurança em tempo de compilação.</p>
<p>Dominar traits é fundamental para escrever código Rust idiomático e reutilizável. Eles habilitam polimorfismo, reduzem duplicação de código e promovem interfaces claras entre componentes.</p>
<h2>Definindo e Implementando Traits</h2>
<h3>Anatomia de um Trait</h3>
<p>Um trait declara um conjunto de métodos que tipos podem implementar. Você define um trait usando a palavra-chave <code>trait</code>, especificando assinaturas de método (com ou sem implementação padrão).</p>
<pre><code class="language-rust">trait Animal {
fn fazer_som(&self) -> String;
fn idade(&self) -> u32;
// Método com implementação padrão
fn apresentar(&self) -> String {
format!("Tenho {} anos", self.idade())
}
}</code></pre>
<h3>Implementação em Tipos Concretos</h3>
<p>Para implementar um trait, você usa o bloco <code>impl TraitName for Type</code>. Todos os métodos requeridos devem ser fornecidos; métodos com implementação padrão podem ser sobrescrito.</p>
<pre><code class="language-rust">struct Cachorro {
nome: String,
anos: u32,
}
impl Animal for Cachorro {
fn fazer_som(&self) -> String {
format!("{} faz: au au!", self.nome)
}
fn idade(&self) -> u32 {
self.anos
}
}
struct Gato {
nome: String,
anos: u32,
}
impl Animal for Gato {
fn fazer_som(&self) -> String {
format!("{} faz: miau!", self.nome)
}
fn idade(&self) -> u32 {
self.anos
}
}
fn main() {
let dog = Cachorro { nome: "Rex".to_string(), anos: 5 };
let cat = Gato { nome: "Whiskers".to_string(), anos: 3 };
println!("{}", dog.fazer_som()); // Rex faz: au au!
println!("{}", cat.apresentar()); // Tenho 3 anos
}</code></pre>
<h2>Trait Objects e Polimorfismo em Tempo de Execução</h2>
<h3>Usando Trait Objects</h3>
<p>Trait objects (<code>&dyn Trait</code> ou <code>Box<dyn Trait></code>) permitem trabalhar com múltiplos tipos que implementam o mesmo trait. Isso viabiliza coleções heterogêneas e despacho dinâmico.</p>
<pre><code class="language-rust">fn fazer_som_animal(animal: &dyn Animal) {
println!("{}", animal.fazer_som());
}
fn main() {
let dog = Cachorro { nome: "Rex".to_string(), anos: 5 };
let cat = Gato { nome: Whiskers".to_string(), anos: 3 };
let animais: Vec<Box<dyn Animal>> = vec![
Box::new(dog),
Box::new(cat),
];
for animal in animais {
fazer_som_animal(&*animal);
}
}</code></pre>
<h3>Limitações de Trait Objects</h3>
<p>Nem todo trait pode ser um trait object. O trait deve ser "object-safe": não pode ter métodos genéricos com Self ou retornar Self, pois o compilador não consegue garantir o tipo em tempo de execução. A maioria dos traits comuns (Display, Iterator, Clone) são object-safe.</p>
<pre><code class="language-rust">// Este trait NÃO é object-safe
trait Clonavel {
fn clonar(&self) -> Self;
}
// Erro: não é possível usar &dyn Clonavel
// let x: &dyn Clonavel = &algum_valor;</code></pre>
<h2>Traits Genéricos e Associados</h2>
<h3>Parâmetros Genéricos em Traits</h3>
<p>Traits podem ser genéricos, permitindo múltiplas implementações para um mesmo tipo com parâmetros diferentes.</p>
<pre><code class="language-rust">trait Conversor<T> {
fn converter(&self) -> T;
}
struct Numero {
valor: i32,
}
impl Conversor<String> for Numero {
fn converter(&self) -> String {
self.valor.to_string()
}
}
impl Conversor<f64> for Numero {
fn converter(&self) -> f64 {
self.valor as f64
}
}
fn main() {
let num = Numero { valor: 42 };
let texto: String = num.converter();
let decimal: f64 = num.converter();
println!("{}, {}", texto, decimal); // 42, 42.0
}</code></pre>
<h3>Tipos Associados</h3>
<p>Tipos associados reduzem a necessidade de parâmetros genéricos, tornando APIs mais simples. Use-os quando há uma relação um-para-um entre o implementador e o tipo.</p>
<pre><code class="language-rust">trait Iterador {
type Item;
fn proximo(&mut self) -> Option<Self::Item>;
}
struct ContadorAte10 {
atual: i32,
}
impl Iterador for ContadorAte10 {
type Item = i32;
fn proximo(&mut self) -> Option<Self::Item> {
if self.atual < 10 {
self.atual += 1;
Some(self.atual)
} else {
None
}
}
}</code></pre>
<h2>Bounds de Trait e Composição</h2>
<p>Trait bounds especificam que um tipo genérico deve implementar certos traits. Eles garantem que você pode usar métodos desses traits com segurança.</p>
<pre><code class="language-rust">fn animar<T: Animal>(animal: &T) {
println!("{}", animal.fazer_som());
println!("Apresentação: {}", animal.apresentar());
}
// Múltiplos bounds
trait Domestico: Animal {
fn treinado(&self) -> bool;
}
fn cuidar<T: Domestico>(pet: &T) {
if pet.treinado() {
println!("Animal bem treinado!");
}
}
// Bounds em structs genéricas
struct Zoologico<T: Animal> {
animais: Vec<T>,
}
impl<T: Animal> Zoologico<T> {
fn fazer_todos_sons(&self) {
for animal in &self.animais {
println!("{}", animal.fazer_som());
}
}
}</code></pre>
<p>Traits podem herdar de outros traits (supertrait), criando hierarquias. Use isso para reutilizar comportamentos comuns sem duplicação.</p>
<h2>Conclusão</h2>
<p>Traits são o mecanismo central de abstração em Rust, permitindo código genérico, polimórfico e seguro. Os três pontos-chave são: <strong>(1)</strong> Traits definem contratos claros de comportamento, promovendo interfaces bem definidas; <strong>(2)</strong> Trait objects habilitam despacho dinâmico para coleções heterogêneas, com o trade-off de runtime overhead; <strong>(3)</strong> Bounds de trait e tipos associados fornecem poder expressivo para escrever código genérico robusto mantendo segurança de tipos em compilação. Com prática, você usará traits naturalmente para estruturar sistemas complexos em Rust.</p>
<h2>Referências</h2>
<ul>
<li><a href="https://doc.rust-lang.org/book/ch10-02-traits.html" target="_blank" rel="noopener noreferrer">The Rust Programming Language - Traits</a></li>
<li><a href="https://doc.rust-lang.org/rust-by-example/trait.html" target="_blank" rel="noopener noreferrer">Rust by Example - Traits</a></li>
<li><a href="https://doc.rust-lang.org/std/trait.html" target="_blank" rel="noopener noreferrer">Rust Standard Library Traits Documentation</a></li>
<li><a href="https://doc.rust-lang.org/book/ch19-03-advanced-traits.html" target="_blank" rel="noopener noreferrer">Advanced Traits - The Book</a></li>
</ul>