0Pricing
Learn Rust Coding · Aula

Objetos de trait e dyn

Despacho dinâmico

Objetos de trait e dyn é uma aula grátis de Learn Rust Coding no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Learn Rust Coding, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Learn Rust Coding inclui 4 aulas no total.

O problema: tipos mistos

Genéricos com restrições de traço funcionam muito bem quando cada chamada usa um único tipo concreto. Mas e se você quiser uma coleção de tipos diferentes que compartilham um traço? Os genéricos não podem conter uma mistura.

Objetos de traço resolvem isso.

O que é um objeto de traço?

Um objeto de traço é um valor referenciado por meio de um ponteiro junto com a palavra-chave dyn, como &dyn Trait ou Box<dyn Trait>.

Ele permite tratar muitos tipos concretos de maneira uniforme durante a execução.

Uma Box de dyn Trait

Box<dyn Trait> possui um valor na memória heap de algum tipo que implementa o traço. Você chama métodos do traço sem conhecer o tipo concreto.

trait Speak { fn say(&self) -> String; }
struct Dog;
impl Speak for Dog { fn say(&self) -> String { String::from("Woof") } }

fn main() {
    let animal: Box<dyn Speak> = Box::new(Dog);
    println!("{}", animal.say());
}

Um Vec de objetos de traço

A grande vantagem: um único vetor pode conter muitos tipos diferentes, desde que cada um implemente o traço.

trait Speak { fn say(&self) -> String; }
struct Dog;
struct Cat;
impl Speak for Dog { fn say(&self) -> String { String::from("Woof") } }
impl Speak for Cat { fn say(&self) -> String { String::from("Meow") } }

fn main() {
    let zoo: Vec<Box<dyn Speak>> = vec![Box::new(Dog), Box::new(Cat)];
    for animal in &zoo {
        println!("{}", animal.say());
    }
}

Despacho dinâmico

Com objetos de traço, o método a ser chamado é escolhido durante a execução, consultando uma tabela oculta, a vtable. Isso é chamado de despacho dinâmico.

O custo é uma pequena indireção; o benefício é a flexibilidade durante a execução.

Funções que retornam objetos de traço

Uma função pode retornar Box<dyn Trait> quando o tipo concreto varia. Isso é útil para funções de fábrica que decidem o tipo durante a execução.

trait Speak { fn say(&self) -> String; }
struct Dog;
struct Cat;
impl Speak for Dog { fn say(&self) -> String { String::from("Woof") } }
impl Speak for Cat { fn say(&self) -> String { String::from("Meow") } }

fn make(kind: &str) -> Box<dyn Speak> {
    if kind == "dog" { Box::new(Dog) } else { Box::new(Cat) }
}

fn main() {
    println!("{}", make("cat").say());
}

Objetos de traço emprestados

Você também pode passar um objeto de traço emprestado com &dyn Trait quando não precisa de propriedade. Nenhuma alocação na memória heap é feita.

trait Speak { fn say(&self) -> String; }
struct Dog;
impl Speak for Dog { fn say(&self) -> String { String::from("Woof") } }

fn announce(s: &dyn Speak) {
    println!("heard: {}", s.say());
}

fn main() {
    let d = Dog;
    announce(&d);
}

Segurança para objetos

Nem todo traço pode ser um objeto de traço. Um traço precisa ser seguro para objetos: em termos gerais, seus métodos não podem retornar Self por valor nem usar parâmetros de tipo genéricos.

Métodos que recebem &self e usam tipos concretos são válidos.

Um exemplo que não é seguro para objetos

Um traço com um método que retorna Self não pode ser usado como dyn, pois o tamanho de Self é desconhecido atrás de um ponteiro. Mantenha simples os traços usados como objetos.

Um exemplo no estilo de plug-in

Os objetos de traço são excelentes para sistemas de plug-ins: armazene uma lista de manipuladores atrás de dyn e execute todos sem se preocupar com os tipos concretos.

trait Task { fn run(&self) -> i32; }
struct Add { a: i32, b: i32 }
struct Negate { x: i32 }
impl Task for Add { fn run(&self) -> i32 { self.a + self.b } }
impl Task for Negate { fn run(&self) -> i32 { -self.x } }

fn main() {
    let tasks: Vec<Box<dyn Task>> = vec![Box::new(Add { a: 2, b: 3 }), Box::new(Negate { x: 7 })];
    let total: i32 = tasks.iter().map(|t| t.run()).sum();
    println!("total {}", total);
}

Quando usar dyn

Use objetos de traço quando precisar de coleções heterogêneas, de tipos escolhidos durante a execução ou de reduzir o excesso de código causado por muitas instanciações genéricas.

Caso contrário, prefira genéricos para obter a máxima velocidade.

Verificação rápida

Teste sua compreensão sobre objetos de traço.

Recapitulação

Você aprendeu sobre despacho dinâmico:

  • Objetos de traço usam dyn atrás de um ponteiro (Box<dyn T>, &dyn T)
  • Eles permitem coleções heterogêneas e tipos escolhidos durante a execução
  • As chamadas de método passam por uma vtable (despacho dinâmico)
  • Os traços precisam ser seguros para objetos para serem usados dessa forma

Perguntas Frequentes

A aula “Objetos de trait e dyn” é grátis?

Sim — o texto completo de “Objetos de trait e dyn” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Learn Rust Coding, atualize para CoddyKit PRO. O curso de Learn Rust Coding inclui 4 aulas no total.

O que vou aprender em “Objetos de trait e dyn”?

Despacho dinâmico Você pratica Learn Rust Coding com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Learn Rust Coding?

Nenhuma experiência prévia é necessária. Learn Rust Coding no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.

Quanto tempo leva a aula “Objetos de trait e dyn”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Learn Rust Coding?

Sim. Cada aula de Learn Rust Coding inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Definição de traits
  2. Objetos de trait e dyn
  3. Despacho estático versus dinâmico
  4. Métodos padrão
← Voltar para Learn Rust Coding