Menu
Coddy logo textTech

Implementações Padrão

Parte da seção Programação Orientada a Objetos 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 método 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 {} vazio é válido porque o trait já fornece o comportamento. A struct simplesmente “opta por participar” do trait e recebe o método padrão 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 padrão 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 padrão. O padrão deve retornar "You have a new notification!". Qualquer tipo que implemente esse trait receberá automaticamente esse comportamento, sem precisar escrever nada em seu bloco impl.
  • alerts.rs: Crie duas structs unitárias públicas simples que implementem seu trait:
    • EmailAlert: implementa Notifiable com um bloco impl vazio (usa o padrão)
    • SystemAlert: também implementa Notifiable com um bloco impl vazio (usa o padrão)
    Ambas as structs receberão automaticamente a mensagem de notificação padrão, sem que você escreva nenhum corpo de método!
  • main.rs: Reúna seus módulos e demonstre como os dois tipos de alerta compartilham o mesmo comportamento padrão. 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 os dois tipos produzem uma saída idêntica: essa é a beleza das implementações padrão! Nenhuma das structs precisou escrever 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 padrões 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 Programação Orientada a Objetos

Pratique por conta própria: Compilador de Rust online