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.
Desafio
FácilVamos 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úblicoNotifiablecom um métodonotify(&self) -> Stringque 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úblicomessage(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 umGenericAlerte umUrgentAlertusando 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
}
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
1Métodos e Comportamento
Introdução a Blocos de ImplementaçãoO Parâmetro SelfMétodos MutáveisFunções AssociadasMúltiplos Blocos de ImplementaçãoEncadeamento de MétodosRecapitulação - Ações de Retângulo4Projeto: Pet Virtual
Definindo o PetAlimentando o Pet7Traits Padrão
A Trait DebugA Trait DisplayClone e CopyTraits de IgualdadeRecapitulação - Ponto Imprimível10Projeto: Sistema de Documentos
A Trait DrawComponente de Texto2Encapsulamento e Módulos
Fundamentos de MódulosA Palavra-chave PublicCampos PrivadosGettersSettersRecapitulação - Cofre Seguro5Genéricos
Structs GenéricasMétodos GenéricosMúltiplos Tipos GenéricosFunções GenéricasRecapitulação - Ponto de Coordenada8Traits como Restrições
Sintaxe de Restrições de TraitRestrições MúltiplasA Cláusula WhereRetornando Tipos com TraitsRecapitulação - Impressora Genérica11Padrões de Projeto em Rust
Padrão NewtypeComposiçãoA Trait DropFrom e IntoRecapitulação - Mock de Smart Pointer3Enums Avançados
Enums com DadosMétodos em EnumsCorrespondência de Variantes de DadosO Enum Option RevisitadoRecapitulação - Enum Shape6Definição de Traits
O que é uma Trait?Implementando TraitsImplementações PadrãoSobrescrevendo PadrõesTraits com ParâmetrosRecapitulação - Media PlayerPratique por conta própria: Compilador de Rust online