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.
Desafio
FácilVamos 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úblicoNotifiablecom um métodonotify(&self) -> Stringque 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: implementaNotifiablecom um bloco impl vazio (usa o padrão)SystemAlert: também implementaNotifiablecom um bloco impl vazio (usa o padrão)
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étodosnotify.
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
}
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