Operadores conscientes de nulos
Parte da seção Programação Orientada a Objetos do Journey de Dart da Coddy. Lição 27 de 110.
Além de ?. e !, o Dart fornece operadores adicionais que tornam o trabalho com valores anuláveis mais conciso. Estes operadores null-aware ajudam você a escrever um código mais limpo ao lidar com possíveis valores nulos.
O operador de coalescência nula ?? retorna o valor da esquerda se ele não for nulo, caso contrário, retorna o valor da direita:
String? nickname;
String displayName = nickname ?? 'Guest';
print(displayName); // Guest
nickname = 'Alex';
displayName = nickname ?? 'Guest';
print(displayName); // AlexO operador de atribuição null-aware ??= atribui um valor apenas se a variável for atualmente nula:
String? username;
username ??= 'Anonymous';
print(username); // Anonymous
username ??= 'NewName';
print(username); // Ainda Anonymous (não era nulo)Você pode encadear o operador de acesso null-aware ?. para propriedades aninhadas:
String? city = user?.address?.city; // Seguro mesmo que user ou address seja nuloEstes operadores combinam bem entre si. Por exemplo, você pode acessar uma propriedade anulável e fornecer um padrão:
String greeting = user?.name ?? 'Stranger';
// Se user for nulo OU user.name for nulo, use 'Stranger'O uso desses operadores mantém seu código legível, ao mesmo tempo em que garante a null safety em todo o seu programa.
Desafio
FácilVamos criar um sistema de registro de convidados que demonstra como os operadores conscientes de nulos podem tornar seu código mais limpo ao lidar com informações opcionais.
Você organizará seu código em dois arquivos:
guest.dart: Defina uma classeGuestque represente alguém participando de um evento. Alguns convidados fornecem todos os detalhes, enquanto outros informam apenas o básico. Sua classe deve ter:- Uma
String namenão anulável — todo convidado deve ter um nome - Uma
String? emailanulável — nem todos fornecem um e-mail - Uma
String? dietaryPreferenceanulável — alguns convidados não especificam necessidades alimentares - Um construtor que recebe
namecomo parâmetro obrigatório - Um método
getDisplayEmail()que retorna o e-mail, se disponível, ou'No email provided'usando o operador?? - Um método
assignDefaultDiet()que definedietaryPreferencecomo'Standard'somente se ele for atualmente nulo, usando o operador??= - Um método
getEmailDomain()que retorna o tamanho do e-mail usando?., ounullse não existir um e-mail - Um método
printBadge()que imprime as informações do crachá do convidado
- Uma
main.dart: Importe sua classe de convidado e registre três convidados com diferentes níveis de informação:- Crie um convidado chamado
'Alice', defina o e-mail dela como'alice@company.com'e a preferência alimentar como'Vegetarian' - Crie um convidado chamado
'Bob', defina apenas o e-mail dele como'bob@email.org'(deixe a preferência alimentar como nula) - Crie um convidado chamado
'Charlie'(deixe tanto o e-mail quanto a preferência alimentar como nulos) - Chame
assignDefaultDiet()nos três convidados - Para cada convidado, na ordem, chame
printBadge()e depois imprimaEmail length: [result]usandogetEmailDomain()
- Crie um convidado chamado
O método printBadge() deve imprimir neste formato:
=== Guest Badge ===
Name: [name]
Email: [getDisplayEmail()]
Diet: [dietaryPreference or "Not specified"]Observe como a preferência alimentar de Alice permanece 'Vegetarian' porque ??= só atribui um valor quando o valor é nulo, enquanto Bob e Charlie recebem a dieta padrão 'Standard'.
Saída esperada:
=== Guest Badge ===
Name: Alice
Email: alice@company.com
Diet: Vegetarian
Email length: 17
=== Guest Badge ===
Name: Bob
Email: bob@email.org
Diet: Standard
Email length: 13
=== Guest Badge ===
Name: Charlie
Email: No email provided
Diet: Standard
Email length: nullExperimente você mesmo
import 'guest.dart';
void main() {
// TODO: Criar uma convidada chamada 'Alice'
// Definir o e-mail dela como 'alice@company.com'
// Definir a preferência alimentar dela como 'Vegetarian'
// TODO: Criar um convidado chamado 'Bob'
// Definir apenas o e-mail dele como 'bob@email.org'
// Deixar a preferência alimentar como null
// TODO: Criar um convidado chamado 'Charlie'
// Deixar tanto o e-mail quanto a preferência alimentar como null
// TODO: Chamar assignDefaultDiet() em todos os três convidados
// TODO: Para cada convidado em ordem (Alice, Bob, Charlie):
// - Chamar printBadge()
// - Imprimir 'Email length: [result]' usando getEmailDomain()
}
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