Retornando Tipos com Traits
Parte da seção Object Oriented Programming do Journey de Rust da Coddy. Lição 43 de 61.
Você usou limites de trait para restringir quais tipos uma function pode aceitar. Mas e quanto ao que uma function retorna? A sintaxe impl Trait permite especificar que uma function retorna "algum tipo que implements este trait" sem nomear o tipo concrete.
Veja a sintaxe em ação:
trait Summary {
fn summarize(&self) -> String;
}
struct Article {
headline: String,
}
impl Summary for Article {
fn summarize(&self) -> String {
self.headline.clone()
}
}
fn create_summary() -> impl Summary {
Article { headline: String::from("Breaking News!") }
}
O tipo de retorno impl Summary informa aos chamadores: "você receberá algo que implementa Summary." O chamador pode usar qualquer método do trait, mas não precisa saber que o tipo real é Article.
Isso é particularmente útil quando o tipo concrete é complexo ou quando você quer ocultar detalhes de implementação. A function promete uma capacidade (o trait), não um tipo específico.
No entanto, há uma limitação importante: a function deve return exatamente um único tipo concrete. Você não pode retornar types different condicionalmente que implement o mesmo trait. Isso requer objetos de trait, sobre os quais você aprenderá mais adiante.
// Isso funciona - sempre retorna Article
fn make_item() -> impl Summary {
Article { headline: String::from("Hello") }
}
// Isso NÃO compilaria - dois tipos diferentes
// fn make_item(flag: bool) -> impl Summary {
// if flag { Article { ... } } else { Tweet { ... } }
// }
Desafio
FácilVamos criar uma fábrica de cartões de saudação que usa o tipo de retorno impl Trait para ocultar os detalhes da implementação! Você criará uma function que retorna "something that can greet" sem revelar o tipo concreto ao chamador.
Você organizará seu código em dois arquivos:
greetings.rs: Defina umGreettrait público com umgreetmethod que recebe&selfe retorna umaString. Em seguida, crie uma structCard(ela não precisa ser pública!) com um campomessage(String). Implemente oGreettrait paraCard, retornando o message. Por fim, crie uma function pública chamadacreate_greetingque recebe um parâmetroStringe retornaimpl Greet. Essa function deve criar e retornar umCardcom o message fornecido.main.rs: Inclua seu módulo greetings e use o input fornecido para chamarcreate_greeting. A parte interessante é que seu arquivo principal não sabe nada sobre o tipoCard. Ele only sabe que recebeu algo que implementsGreet. Chame ogreetmethod no valor retornado e print o result.
A principal ideia é que Card permanece privado para o módulo, mas os chamadores ainda podem usá-lo por meio da interface do trait. A function promete uma capacidade (saudação), não um tipo específico.
Sua saída deve exibir a saudação:
{message}Por exemplo, com o input Happy Birthday!:
Happy Birthday!E com o input Congratulations on your promotion!:
Congratulations on your promotion!Você receberá um input: o message de saudação.
Experimente você mesmo
mod greetings;
use greetings::Greet;
fn main() {
// Leia a mensagem de saudação da entrada
let mut input = String::new();
std::io::stdin().read_line(&mut input).expect("Failed to read line");
let message = input.trim().to_string();
// TODO: Chame create_greeting com a mensagem
// Note: Você não conhece o tipo concreto - apenas que ele implementa Greet!
// TODO: Chame o método greet e imprima o resultado
}
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
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