Menu
Coddy logo textTech

Implementações Padrão

Parte da seção Object Oriented Programming do Journey de Rust da Coddy. Lição 31 de 61.

Até agora, todo método de trait que definimos foi apenas uma assinatura: um requisito sem corpo. Mas e se a maioria dos tipos que implementam uma trait usasse a mesma lógica? Rust permite fornecer uma implementação padrão diretamente na definição da trait.

Em vez de terminar a assinatura do method com um ponto e vírgula, você adiciona um corpo:

trait Greet {
    fn greet(&self) -> String {
        String::from("Hello there!")
    }
}

Agora, qualquer tipo que implemente Greet obtém automaticamente este método, sem escrever nenhum código no bloco impl:

struct Guest;

impl Greet for Guest {}

let visitor = Guest;
println!("{}", visitor.greet());  // Olá!

O impl Greet for Guest {} empty é válido porque o trait já fornece o comportamento. O struct simplesmente “opta” pelo trait e recebe o default method gratuitamente.

Este padrão é útil quando você quer definir um comportamento compartilhado que funcione na maioria dos casos. Os tipos que precisam de algo diferente podem substituir o default (que você aprenderá a seguir), enquanto os tipos que estão satisfeitos com o comportamento padrão não precisam se repetir.

challenge icon

Desafio

Fácil

Vamos explorar o poder das implementações default construindo um sistema de notificações! Você criará um trait que fornece um comportamento padrão pronto para uso, para que os tipos possam optar por ele sem escrever código repetitivo.

Você organizará seu código em três arquivos:

  • notifiable.rs: Defina um trait público Notifiable com um método notify(&self) -> String que tenha uma implementação default. O default deve retornar "You have a new notification!". Qualquer tipo que implemente esse trait receberá automaticamente esse comportamento sem precisar escrever nada em seu block impl.
  • alerts.rs: Crie duas structs unit públicas simples que implementem seu trait:
    • EmailAlert: implementa Notifiable com um block impl vazio (usa o default)
    • SystemAlert: também implementa Notifiable com um block impl vazio (usa o default)
    Ambas as structs receberão automaticamente a mensagem de notificação default sem que você escreva nenhum corpo de método!
  • main.rs: Reúna seus módulos e demonstre como ambos os tipos de alerta compartilham o mesmo comportamento default. Crie instâncias de ambas as structs e chame seus métodos notify.

Em seu arquivo principal, crie um EmailAlert e um SystemAlert e, em seguida, imprima suas notificações em linhas separadas.

Sua saída deve ser:

You have a new notification!
You have a new notification!

Observe como ambos os tipos produzem uma saída idêntica: essa é a beleza das implementações default! Nenhuma das structs precisou escrever qualquer código para o método notify, mas ambas têm um comportamento de notificação totalmente funcional. Na próxima lição, você aprenderá a substituir esses defaults quando um tipo precisar de um comportamento personalizado.

Experimente você mesmo

mod notifiable;
mod alerts;

use notifiable::Notifiable;
use alerts::{EmailAlert, SystemAlert};

fn main() {
    // TODO: Crie uma instância de EmailAlert
    
    // TODO: Crie uma instância de SystemAlert
    
    // TODO: Print the notification from EmailAlert
    
    // TODO: Print the notification from SystemAlert
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Object Oriented Programming

Pratique por conta própria: Compilador de Rust online