Construtores assíncronos
Parte da seção Programação Orientada a Objetos do Journey de Dart da Coddy. Lição 79 de 110.
Construtores em Dart não podem ser marcados como async - eles devem retornar uma instância da classe imediatamente, não um Future. Então, como você cria objetos que precisam de inicialização assíncrona, como carregar dados de um banco de dados ou buscar configurações?
A solução é usar um método de fábrica assíncrono estático. Mantenha o construtor privado (ou simples) e forneça um método estático que execute o trabalho assíncrono e retorne um Future da sua classe:
class UserProfile {
final String name;
final int age;
UserProfile._(this.name, this.age); // Construtor privado
static Future<UserProfile> create(String userId) async {
// Simula a busca de dados
await Future.delayed(Duration(seconds: 1));
return UserProfile._('Alice', 25);
}
}
Future<void> main() async {
var user = await UserProfile.create('123');
print(user.name); // Alice
}O construtor privado UserProfile._ lida com a criação real do objeto, enquanto o método estático create() lida com todo o trabalho assíncrono. Os chamadores usam await para obter o objeto totalmente inicializado.
Este padrão garante que seu objeto esteja completamente pronto para uso assim que você o tiver — sem estados parcialmente inicializados ou dados ausentes. É comumente usado para classes que precisam carregar recursos, conectar-se a serviços ou realizar qualquer configuração que leve tempo.
Desafio
FácilVamos criar um carregador de configurações que demonstra como lidar com a inicialização assíncrona em classes! Como os construtores não podem ser assíncronos, você usará o padrão de método de fábrica estático para criar objetos que precisam de tempo para "carregar" seus dados.
Você organizará seu código em dois arquivos:
config_loader.dart: crie uma classeConfigLoaderque simula o carregamento assíncrono das configurações. Sua classe deve ter:- Três campos finais:
appName(String),version(String) emaxUsers(int) - Um construtor privado que inicializa os três campos
- Um método de fábrica assíncrono estático chamado
loadque recebe um parâmetroString configIde retorna umFuture<ConfigLoader>. Esse método deve:- Usar
Future.delayed()com 100 milissegundos para simular o tempo de carregamento - Gerar os valores da configuração com base em
configId:appName: o configId com" App"anexadoversion:"1.0."seguido pelo comprimento de configIdmaxUsers: o comprimento de configId multiplicado por 10
- Retornar uma nova instância de
ConfigLoadercom esses valores
- Usar
- Um método
displayInfo()que imprime a configuração neste formato:Config: [appName] v[version] (max [maxUsers] users)
- Três campos finais:
main.dart: importe seu carregador de configurações e demonstre o padrão de inicialização assíncrona:- Imprima
Loading configurations... - Carregue uma configuração com configId
"Production"e chame seudisplayInfo() - Carregue uma configuração com configId
"Dev"e chame seudisplayInfo() - Imprima
All configs loaded!
- Imprima
Observe como o método estático load lida com todo o trabalho assíncrono, enquanto o construtor privado simplesmente atribui os valores. Os chamadores usam await para obter um objeto totalmente inicializado!
Saída esperada:
Loading configurations...
Config: Production App v1.0.10 (max 100 users)
Config: Dev App v1.0.3 (max 30 users)
All configs loaded!Experimente você mesmo
import 'config_loader.dart';
void main() async {
// TODO: Imprima "Loading configurations..."
// TODO: Carregue uma configuração com configId "Production"
// e chame seu método displayInfo()
// TODO: Carregue uma configuração com configId "Dev"
// e chame seu método displayInfo()
// TODO: Imprima "All configs loaded!"
}
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
1Fundamentos de OOP
Arquivos externosBibliotecas e importsIntrodução à OOPClasses vs. objetosA palavra-chave thisMétodosVariáveis de instânciaNoções básicas de construtoresRevisão - Calculadora simples4Segurança contra nulos
Introdução à segurança contra nulosAnulável vs. não anulávelOs operadores ? e !Palavra-chave Late e segurança contra nulosOperadores conscientes de nulosSegurança contra nulos em classesRecapitulação — Sistema de perfil de usuário7Classes Abstratas e Interfaces
Classes AbstratasMétodos AbstratosInterfaces em DartInterfaces ImplícitasImplementação vs. ExtensãoMúltiplas InterfacesRecapitulação - Calculadora de Formas10Coleções e Genéricos
Visão geral de List, Set e MapColeções com segurança de tiposClasses genéricasMétodos genéricosRestrições genéricasIterable e IteratorRecapitulação - Armazenamento genérico13Conceitos Avançados de OOP
Composição vs. HerançaMétodos de ExtensãoClasses ChamáveisClasses Seladas (Dart 3)Registros (Dart 3)Padrões e Correspondência (3.0)Enums com Métodos16Projeto: Gerenciamento de Biblioteca
Visão Geral do ProjetoClasses de Livros e Usuários2Construtores em Dart
Construtor padrãoConstrutores nomeadosListas de inicializaçãoConstrutores constantesConstrutores factoryConstrutores de redirecionamentoRevisão - Construtor de formas5Encapsulamento
Membros Públicos vs. PrivadosConvenção do Prefixo _Privacidade no Nível da BibliotecaAprofundamento em Getters e SettersOcultação de InformaçõesRecapitulação - Registros de Alunos8Mixins
Introdução a MixinsCriando MixinsUsando vários MixinsPalavra-chave on em MixinsMixin vs HerançaMixin vs InterfaceRecapitulação - Sistema de Animais11Métodos Especiais
Sobrescrita de toString()Sobrescrita de hashCode e ==Interface ComparableMétodo call()Sobrescrita de noSuchMethodRecapitulação - Coleção Personalizada14Padrões de Projeto – Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão ObserverPadrão Strategy3Propriedades de Classe
Membros de Instância vs. EstáticosCampos Final e ConstVariáveis LateMétodos e Campos EstáticosGetters e SettersRecapitulação - Gerenciador de Contas Bancárias6Herança
Herança BásicaA Palavra-chave superSobrescrita de MétodosA Anotação @overrideA Palavra-chave final para ClassesConstrutores e HerançaRecapitulação - Hierarquia de Funcionários9Polimorfismo
Fundamentos do polimorfismoPolimorfismo por meio de interfacesVerificação de tipos em tempo de execuçãoOs operadores is e asPalavra-chave covarianteRecapitulação — Processador de pagamentos12OOP Assíncrona
Futures e async/awaitNoções básicas de StreamsControladores de StreamConstrutores assíncronosAsync em métodos de classeRecapitulação — Buscador de dados15Padrões de Projeto — Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão CompositePadrão RepositoryPratique por conta própria: Compilador de Dart online