Exercício: Tipo Builder
Neste exemplo, implementaremos um tipo de dados complexo que possui todos os seus dados. Usaremos o "builder pattern" para suportar a construção de um novo valor peça por peça, usando funções de conveniência.
Preencha as peças que faltam.
#[derive(Debug)] enum Language { Rust, Java, Perl, } #[derive(Clone, Debug)] struct Dependency { name: String, version_expression: String, } /// Uma representação de um pacote de software. #[derive(Debug)] struct Package { name: String, version: String, authors: Vec<String>, dependencies: Vec<Dependency>, language: Option<Language>, } impl Package { /// Retorna uma representação deste pacote como uma dependência, para uso na /// construção de outros pacotes. fn as_dependency(&self) -> Dependency { todo!("1") } } /// Um construtor para um Pacote. Use `build()` para criar o próprio `Package`. struct PackageBuilder(Package); impl PackageBuilder { fn new(name: impl Into<String>) -> Self { todo!("2") } /// Define a versão do pacote. fn version(mut self, version: impl Into<String>) -> Self { self.0.version = version.into(); self } /// Define os autores do pacote. fn authors(mut self, authors: Vec<String>) -> Self { todo!("3") } /// Adiciona uma dependência adicional. fn dependency(mut self, dependency: Dependency) -> Self { todo!("4") } /// Define a linguagem. Se não definida, a linguagem é None. fn language(mut self, language: Language) -> Self { todo!("5") } fn build(self) -> Package { self.0 } } fn main() { let base64 = PackageBuilder::new("base64").version("0.13").build(); println!("base64: {base64:?}"); let log = PackageBuilder::new("log").version("0.4").language(Language::Rust).build(); println!("log: {log:?}"); let serde = PackageBuilder::new("serde") .authors(vec!["djmitche".into()]) .version(String::from("4.0")) .dependency(base64.as_dependency()) .dependency(log.as_dependency()) .build(); println!("serde: {serde:?}"); }