Menu
Coddy logo textTech

Os Operadores ? e !

Parte da seção Programação Orientada a Objetos do Journey de Dart da Coddy — lição 25 de 110.

Ao trabalhar com tipos anuláveis, o Dart fornece dois operadores essenciais para acessar valores com segurança. O operador de acesso condicional (null-aware) ?. e o operador de asserção nula (null assertion) ! oferecem controle sobre como você lida com valores potencialmente nulos.

O operador ?. acessa com segurança propriedades ou métodos em um valor anulável. Se o valor for null, toda a expressão retornará null em vez de causar um erro:

String? name = 'Alice';
print(name?.length);  // 5

name = null;
print(name?.length);  // null (sem erro!)

O operador ! informa ao Dart: "Tenho certeza de que este valor não é null". Ele converte um tipo nullable em non-nullable, mas lança um erro se o valor for realmente null:

String? maybeName = 'Bob';
String definite = maybeName!;  // OK - afirmamos que não é nulo
print(definite.length);  // 3

String? empty = null;
// String crash = empty!;  // Erro de tempo de execução! O valor era nulo

Use ?. quando você quiser lidar graciosamente com valores nulos. Use ! apenas quando tiver certeza absoluta de que um valor existe - talvez após verificá-lo com uma instrução if ou quando souber que a lógica garante um valor. O uso excessivo de ! anula o propósito da segurança de nulos (null safety) e pode levar a falhas em tempo de execução.

challenge icon

Desafio

Fácil

Vamos construir um sistema de inventário de produtos que demonstra como trabalhar com segurança com valores anuláveis usando os operadores ?. e !.

Você criará dois arquivos para organizar seu código:

  • product.dart: Defina uma classe Product que representa um item no inventário. Alguns produtos possuem informações completas, enquanto outros ainda estão sendo catalogados. Sua classe deve ter:
    • Um String name não anulável - todo produto deve ter um nome
    • Um double price não anulável - todo produto deve ter um preço
    • Um String? description anulável - alguns produtos ainda não possuem descrições
    • Um String? category anulável - alguns produtos ainda não foram categorizados
    • Um construtor que recebe name e price como parâmetros obrigatórios
    • Um método getDescriptionLength() que retorna o comprimento da descrição usando ?., ou null se não houver descrição
    • Um método getCategoryUppercase() que retorna a categoria em letras maiúsculas usando ! - este método assume que a categoria foi definida
    • Um método displayProduct() que imprime as informações do produto, exibindo "No description" quando a descrição for nula e "Uncategorized" quando a categoria for nula
  • main.dart: Importe sua classe de produto e demonstre ambos os operadores:
    • Crie um produto chamado 'Laptop' com o preço 999.99, depois defina sua descrição como 'High-performance computing device' e a categoria como 'Electronics'
    • Crie um produto chamado 'Mystery Item' com o preço 49.99 (deixe a descrição e a categoria como nulas)
    • Para o Laptop: chame displayProduct(), imprima Description length: [length] usando getDescriptionLength(), e imprima Category: [uppercase] usando getCategoryUppercase()
    • Para o Mystery Item: chame displayProduct() e imprima Description length: [length] usando getDescriptionLength() (isso mostrará null)

O método displayProduct() deve imprimir neste formato:

Product: [name] - $[price]
Description: [description or "No description"]
Category: [category or "Uncategorized"]

Saída esperada:

Product: Laptop - $999.99
Description: High-performance computing device
Category: Electronics
Description length: 32
Category: ELECTRONICS
Product: Mystery Item - $49.99
Description: No description
Category: Uncategorized
Description length: null

Folha de consulta

O operador de acesso null-aware ?. acessa com segurança propriedades ou métodos em valores anuláveis (nullable). Se o valor for nulo, ele retorna nulo em vez de lançar um erro:

String? name = 'Alice';
print(name?.length);  // 5

name = null;
print(name?.length);  // null (sem travamentos!)

O operador de asserção nula ! converte um tipo anulável para não anulável. Use-o apenas quando tiver certeza de que o valor não é nulo, pois ele lançará um erro de tempo de execução se o valor for realmente nulo:

String? maybeName = 'Bob';
String definite = maybeName!;  // OK - afirma que não é nulo
print(definite.length);  // 3

String? empty = null;
// String crash = empty!;  // Erro de tempo de execução!

Use ?. para um tratamento de nulos gracioso e ! apenas quando tiver certeza absoluta de que um valor existe.

Experimente você mesmo

import 'product.dart';

void main() {
  // TODO: Crie um produto chamado 'Laptop' com o preço 999.99
  // Depois, defina sua descrição como 'High-performance computing device'
  // E defina sua categoria como 'Electronics'
  
  // TODO: Crie um produto chamado 'Mystery Item' com o preço 49.99
  // Deixe a descrição e a categoria como null
  
  // TODO: Para o Laptop:
  // - Chame displayProduct()
  // - Imprima "Description length: [length]" usando getDescriptionLength()
  // - Imprima "Category: [uppercase]" usando getCategoryUppercase()
  
  // TODO: Para o Mystery Item:
  // - Chame displayProduct()
  // - Imprima "Description length: [length]" usando getDescriptionLength()
}
quiz iconTeste seus conhecimentos

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