Menu
Coddy logo textTech

Sobrescrevendo Padrões

Parte da seção Programação Orientada a Objetos do Journey de Rust da Coddy. Lição 32 de 61.

Implementações padrão são convenientes, mas às vezes um tipo precisa de um comportamento diferente do padrão. Quando isso acontece, você pode substituir o padrão fornecendo sua própria implementação no bloco impl.

Simplesmente defina o método com a mesma assinatura, mas inclua sua lógica personalizada:

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

struct Robot {
    id: u32,
}

impl Greet for Robot {
    fn greet(&self) -> String {
        format!("BEEP BOOP. Unit {} online.", self.id)
    }
}

Embora Greet forneça um método greet padrão, Robot o substitui completamente por sua própria versão. Quando você chama greet() em um Robot, Rust usa a implementação personalizada:

let bot = Robot { id: 42 };
println!("{}", bot.greet());  // BEEP BOOP. Unidade 42 online.

Isso oferece flexibilidade: os tipos que estão satisfeitos com o padrão não precisam escrever nada, enquanto os tipos que precisam de um comportamento especializado podem substituir apenas os métodos com os quais se importam. O trait ainda garante que todo tipo que o implementa tenha o método disponível.

challenge icon

Desafio

Fácil

Vamos criar um sistema de notificações em que diferentes tipos de alerta podem personalizar suas mensagens! Você criará um trait com uma implementação padrão e, em seguida, fará com que um tipo use o padrão enquanto outro o substitui por um comportamento personalizado.

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 retornando "Alert: Something happened!".
  • alerts.rs: crie duas structs públicas que implementem seu trait de maneiras diferentes:
    • GenericAlert: uma struct unitária que usa a notificação padrão (bloco impl vazio)
    • UrgentAlert: uma struct com um campo público message (String) que substitui o padrão para retornar "URGENT: {message}", em que {message} é sua mensagem armazenada
  • main.rs: reúna seus módulos e demonstre os dois comportamentos. Crie um GenericAlert e um UrgentAlert usando a entrada fornecida e, em seguida, exiba suas notificações.

A principal ideia aqui é que GenericAlert obtém um comportamento gratuito da implementação padrão, enquanto UrgentAlert fornece sua própria versão especializada ao definir o método em seu bloco impl.

Sua saída deve seguir este formato:

Alert: Something happened!
URGENT: {message}

Por exemplo, com a entrada Server is down!:

Alert: Something happened!
URGENT: Server is down!

Você receberá uma entrada: a mensagem para o alerta urgente.

Experimente você mesmo

mod notifiable;
mod alerts;

use alerts::{GenericAlert, UrgentAlert};
use notifiable::Notifiable;

fn main() {
    // Ler a entrada para a mensagem do alerta urgente
    let mut input = String::new();
    std::io::stdin().read_line(&mut input).expect("Failed to read line");
    let message = input.trim().to_string();

    // TODO: Criar uma instância de GenericAlert

    // TODO: Criar uma instância de UrgentAlert com a mensagem de entrada

    // TODO: Imprimir a notificação de GenericAlert

    // TODO: Imprimir a notificação de UrgentAlert
}
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