Menu
Coddy logo textTech

Sobrescrevendo Padrões

Parte da seção Object Oriented Programming 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 que difere do padrão. Quando isso acontece, você pode sobrescrever o padrão fornecendo sua própria implementação no bloco impl.

Basta definir o método com a mesma assinatura, mas incluir 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 inteiramente por sua própria versão. Quando você chama greet() em um Robot, o Rust usa a implementação personalizada:

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

Isso oferece flexibilidade — tipos que estão satisfeitos com o padrão não precisam escrever nada, enquanto tipos que precisam de comportamento especializado podem sobrescrever apenas os métodos com os quais se preocupam. A trait ainda garante que cada tipo implementador tenha o método disponível.

challenge icon

Desafio

Fácil

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

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

  • notifiable.rs: Defina uma trait pública Notifiable com um método notify(&self) -> String que possui uma implementação padrão retornando "Alert: Something happened!".
  • alerts.rs: Crie duas structs públicas que implementam sua trait de forma diferente:
    • GenericAlert — uma unit struct que usa a notificação padrão (bloco impl vazio)
    • UrgentAlert — uma struct com um campo público message (String) que sobrescreve o padrão para retornar "URGENT: {message}" onde {message} é a sua mensagem armazenada
  • main.rs: Reúna seus módulos e demonstre ambos os comportamentos. Crie um GenericAlert e um UrgentAlert usando a entrada fornecida e, em seguida, imprima suas notificações.

O ponto principal aqui é que o GenericAlert recebe o comportamento gratuito do padrão, enquanto o UrgentAlert fornece sua própria versão especializada definindo 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.

Folha de consulta

Você pode sobrescrever as implementações padrão de traits fornecendo sua própria implementação no bloco impl:

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)
    }
}

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

Tipos que não precisam de comportamento personalizado podem usar um bloco impl vazio para aceitar a implementação padrão, enquanto tipos que exigem comportamento especializado podem sobrescrever métodos específicos definindo-os com a mesma assinatura.

Experimente você mesmo

mod notifiable;
mod alerts;

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

fn main() {
    // Lê a entrada para a mensagem de 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 Object Oriented Programming