Variáveis e Tipos de Dados no Dart

Variáveis são contêineres para dados, e tipos são a forma do contêiner — escolha o contêiner certo e seu código será seguro.

1. O que Você Aprenderá


2. A História Real de um Desenvolvedor

(1) Dor: Crashes em tempo de execução causados por declarações de variáveis descuidadas

Quando Bob estava desenvolvendo a versão inicial do DataPipeline, declarou todas as variáveis com var e frequentemente mudava seus tipos no meio do caminho. Durante um refactor, ele mudou int orderCount para String orderCount por engano. A compilação não reportou erro (tipo dinâmico), mas em tempo de execução, orderCount * price lançou uma exceção, causando a interrupção do processamento em lote de 500.000 pedidos e atrasando a entrega do relatório em 4 horas.

(2) A Solução Type-Safe

O Dart oferece uma gama de métodos de declaração do mais solto ao mais estrito: const (constante em tempo de compilação) → final (constante em tempo de execução) → var (tipo inferido) → late (inicialização preguiçosa) → dynamic (tipo dinâmico). Usá-los apropriadamente permite que o compilador ajude você a encontrar bugs.

DART
// Melhor prática para configuração do DataPipeline
const int maxRecords = 1000000;       // Constante em tempo de compilação
final String pipelineName;             // Constante em tempo de execução (definida uma vez)
var processedCount = 0;                // Inferido como int, mutável
late String outputPath;                // Inicializado depois
// dynamic deve ser evitado se possível
TEXT
> Saída: Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x, e os resultados podem variar ligeiramente dependendo da versão do SDK.

(3) Benefícios


3. Cinco Formas de Declaração

(1) Árvore de Decisão de Declaração

100%
graph LR
  subgraph Declarations
    A[var] --> B[Inferência de tipo]
    C[final] --> D[Constante em runtime]
    E[const] --> F[Constante em tempo de compilação]
    G[late] --> H[Inicialização preguiçosa]
    I[dynamic] --> J[Tipo dinâmico]
  end
  subgraph Built-in Types
    K[int] --- L[double]
    M[String] --- N[bool]
  end
TEXT
> Saída: Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x, e os resultados podem variar ligeiramente dependendo da versão do SDK.

▶ Exemplo

TEXT
> Saída: Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x, e os resultados podem variar ligeiramente dependendo da versão do SDK.

: var — Inferência de Tipo

DART
void main() {
  var name = 'DataPipeline';   // Inferido como String
  var count = 1000;            // Inferido como int
  var rate = 0.08;             // Inferido como double

  // Pode reatribuir mesmo tipo
  name = 'Analytics';          // OK - ainda String
  count = 2000;                // OK - ainda int

  // Não pode mudar tipo
  // count = 'two thousand';   // Erro de compilação!
}
TEXT
> Saída: Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x, e os resultados podem variar ligeiramente dependendo da versão do SDK.

▶ Exemplo

TEXT
> Saída: Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x, e os resultados podem variar ligeiramente dependendo da versão do SDK.

: final — Constante em Tempo de Execução

DART
void main() {
  // Definida uma vez em runtime
  final DateTime startTime = DateTime.now();
  final String configPath = '/etc/datapipeline/config.yaml';

  // Não pode reatribuir
  // configPath = '/other/path';  // Erro de compilação!

  // final com coleção - conteúdo pode mudar
  final List<String> sources = ['orders.csv', 'products.csv'];
  sources.add('customers.csv');   // OK - modificando conteúdo
  // sources = ['new_list'];       // Erro - não pode reatribuir referência
}
TEXT
> Saída: Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x, e os resultados podem variar ligeiramente dependendo da versão do SDK.

▶ Exemplo

TEXT
> Saída: Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x, e os resultados podem variar ligeiramente dependendo da versão do SDK.

: const — Constante em Tempo de Compilação

DART
void main() {
  // Deve ser conhecido em tempo de compilação
  const int maxRecords = 1000000;
  const double taxRate = 0.08;
  const String version = '1.0.0';

  // Coleções const são profundamente imutáveis
  const List<String> formats = ['json', 'csv', 'html'];
  // formats.add('xml');  // Erro! Não pode modificar lista const

  // Construtor const
  const config = PipelineConfig(batchSize: 10000);
}
TEXT
> Saída: Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x, e os resultados podem variar ligeiramente dependendo da versão do SDK.

▶ Exemplo

TEXT
> Saída: Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x, e os resultados podem variar ligeiramente dependendo da versão do SDK.

: late — Inicialização Preguiçosa

DART
class DataPipeline {
  late String outputPath;  // Será definido depois

  void configure(String path) {
    outputPath = path;
  }

  late final int maxRecords = _loadMaxRecords();  // Computado no primeiro acesso

  int _loadMaxRecords() {
    print('Loading max records config...');
    return 1000000;
  }
}
TEXT
> Saída: Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x, e os resultados podem variar ligeiramente dependendo da versão do SDK.

▶ Exemplo

TEXT
> Saída: Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x, e os resultados podem variar ligeiramente dependendo da versão do SDK.

: dynamic — Tipo Dinâmico

DART
void main() {
  dynamic value = 'hello';   // String
  value = 42;                // OK - agora int
  value = [1, 2, 3];        // OK - agora List

  // Sem verificação de tipo em tempo de compilação - arriscado!
  // value.nonExistentMethod();  // Sem erro de compilação, crash em runtime

  // Prefira Object? ao invés de dynamic quando precisar de flexibilidade
  Object? safeValue = 'test';
  // safeValue.nonExistentMethod();  // Erro de compilação - mais seguro
}
TEXT
> Saída: Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x, e os resultados podem variar ligeiramente dependendo da versão do SDK.

(2) Comparação das Cinco Formas de Declaração

Forma de Declaração Tipo Mutável Momento da Inicialização Segurança Caso de Uso
const Determinado em tempo de compilação Imutável Na declaração Mais alta Constantes de configuração, valores de enum
final Determinado em runtime Imutável Na declaração ou no construtor Alta Configuração de runtime, valores injetados
var Inferido Mutável Na declaração Média Variáveis locais, contadores
late Anotado explicitamente Mutável Adiada Média Campos de inicialiação adiada
dynamic Runtime Mutável A qualquer momento Baixa Parsing JSON, interoperabilidade

4. Tipos Embutidos em Detalhe

(1) Tipos Numéricos

▶ Exemplo

TEXT
> Saída: Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x, e os resultados podem variar ligeiramente dependendo da versão do SDK.

: int e double

DART
void main() {
  int orderCount = 1500;
  double totalAmount = 52500.75;
  num genericNum = 42;      // num é supertipo de int e double
  genericNum = 3.14;        // OK - num aceita ambos

  // Operações aritméticas
  double avgOrderValue = totalAmount / orderCount;
  int roundedDown = totalAmount.toInt();

  // Métodos convenientes
  print(totalAmount.toStringAsFixed(2));  // 52500.75
  print(orderCount.isEven);              // false (1500 is even, true)
  print(orderCount.clamp(0, 1000));      // 1000 (clamped to max)
}
TEXT
> Saída: Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x, e os resultados podem variar ligeiramente dependendo da versão do SDK.
Tipo Intervalo Propósito
int 64-bit (varia no JS) Contagem, indexação
double 64-bit IEEE 754 Valores, proporções
num Supertipo de int + double Valores numéricos gerais

(2) Tipo String

▶ Exemplo

TEXT
> Saída: Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x, e os resultados podem variar ligeiramente dependendo da versão do SDK.

: Interpolação de Strings e Operações

DART
void main() {
  // Interpolação de strings
  String product = 'DataPipeline';
  int users = 5000;
  print('$product has $users users');               // Interpolação simples
  print('Revenue: ${users * 99} USD');              // Interpolação de expressão
  print('Average: ${(125000 / users).toStringAsFixed(2)} USD');

  // Strings de múltiplas linhas
  String description = '''
  DataPipeline - E-Commerce Analytics Tool
  Processes up to 1,000,000 orders per batch
  Supports JSON, CSV, and HTML output formats
  ''';

  // Raw strings (sem processamento de escape)
  String path = r'C:\Users\Bob\data\orders.csv';
  String regex = r'\d{4}-\d{2}-\d{2}';  // Padrão de data

  // Métodos úteis
  String raw = '  Hello, World!  ';
  print(raw.trim());                  // 'Hello, World!'
  print(raw.toUpperCase());           // '  HELLO, WORLD!  '
  print('USD 1,500.00'.replaceAll(',', ''));  // 'USD 1500.00'
}
TEXT
> Saída: Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x, e os resultados podem variar ligeiramente dependendo da versão do SDK.
Recurso Sintaxe Exemplo
Interpolação simples $variable '$name'
Interpolação de expressão ${expr} '${a + b}'
Strings de múltiplas linhas '''...''' Triplas aspas
Raw strings r'...' r'\n' permanece como está

(3) Tipo bool

▶ Exemplo

TEXT
> Saída: Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x, e os resultados podem variar ligeiramente dependendo da versão do SDK.

: Valores Booleanos e Condições

DART
void main() {
  bool isProduction = true;
  bool isDebug = false;

  // Dart requer bool explícito em condições
  int count = 0;
  // if (count) {}  // Erro! Deve ser bool
  if (count > 0) {  // OK - comparação explícita
    print('Has records');
  }

  // Operadores lógicos
  bool shouldProcess = isProduction && !isDebug;
  bool hasData = count > 0 || isProduction;
}
TEXT
> Saída: Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x, e os resultados podem variar ligeiramente dependendo da versão do SDK.

5. Inferência de Tipos e Anotação Explícita

(1) Melhores Práticas

DART
// Bom - deixe o compilador inferir para variáveis locais
var name = 'DataPipeline';     // Inferido String
var count = 100;               // Inferido int
var items = <String>[];        // Genérico explícito, inferido List

// Bom - tipo explícito para API pública
String get displayName => name;
int get maxCapacity => 1000000;

// Bom - final para valores que não mudam
final startTime = DateTime.now();

// Evitar - tipo explícito desnecessário em locais
// String name = 'DataPipeline';  // Redundante
// int count = 100;               // Redundante
TEXT
> Saída: Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x, e os resultados podem variar ligeiramente dependendo da versão do SDK.
Cenário Recomendação Motivo
Variáveis locais var / final Reduz redundância, inferência é suficiente
API pública Anotação explícita Documentação clara, interface estável
Genéricos de coleção Genérico explícito Evita inferência como List<dynamic>
Parâmetros de construtor Anotação explícita Contrato claro

6. Cenário do Bob: Variáveis de Configuração do DataPipeline

▶ Exemplo

TEXT
> Saída: Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x, e os resultados podem variar ligeiramente dependendo da versão do SDK.

: Design de Variáveis de Configuração

DART
// Constantes de configuração do DataPipeline
const String appName = 'DataPipeline';
const int defaultBatchSize = 10000;
const double defaultTaxRate = 0.08;

// Configuração de runtime
class PipelineConfig {
  final String version;
  final int batchSize;
  final String outputFormat;

  PipelineConfig({
    this.version = '1.0.0',
    this.batchSize = defaultBatchSize,
    this.outputFormat = 'json',
  });

  @override
  String toString() =>
      '$appName v$version | Batch: $batchSize | Format: $outputFormat';
}
TEXT
> Saída: Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x, e os resultados podem variar ligeiramente dependendo da versão do SDK.

7. Exemplo Completo: Declaração de Variáveis do DataPipeline na Prática

DART
// ============================================
// Demo de Declaração de Variáveis do DataPipeline
// Mostra uso adequado de todos os tipos de declaração
// ============================================

// Constantes em tempo de compilação - nunca mudam entre execuções
const String appName = 'DataPipeline';
const int maxRecords = 1000000;
const double taxRate = 0.08;
const List<String> supportedFormats = ['json', 'csv', 'html'];

class Order {
  final String id;          // Constante de runtime após construção
  final double amount;      // Constante de runtime após construção
  late String status;       // Será definido pela lógica de processamento

  Order({required this.id, required this.amount});

  double get tax => amount * taxRate;
  double get total => amount + tax;

  String get formattedAmount =>
      '\$${amount.toStringAsFixed(2)} USD';
}

class DataPipeline {
  final String name;
  var processedCount = 0;              // Contador mutável
  late final DateTime startTime;       // Definido na primeira execução

  DataPipeline({required this.name});

  void start() {
    startTime = DateTime.now();
    print('$appName started at $startTime');
  }

  void processOrder(Order order) {
    processedCount++;
    order.status = 'processed';
    print('Order ${order.id}: ${order.formattedAmount} '
        '(tax: \$${order.tax.toStringAsFixed(2)} USD)');
  }

  void printSummary() {
    print('\n=== Summary ===');
    print('Pipeline: $name');
    print('Processed: $processedCount orders');
    print('Capacity: $processedCount / $maxRecords');
  }
}

void main() {
  final pipeline = DataPipeline(name: 'E-Commerce Analytics');
  pipeline.start();

  final orders = [
    Order(id: 'ORD-001', amount: 1500.00),
    Order(id: 'ORD-002', amount: 3250.50),
    Order(id: 'ORD-003', amount: 890.25),
  ];

  for (final order in orders) {
    pipeline.processOrder(order);
  }

  pipeline.printSummary();
}
TEXT
> Saída: Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x, e os resultados podem variar ligeiramente dependendo da versão do SDK.

Saída:

TEXT
DataPipeline started at 2024-01-15 10:30:00.000
Order ORD-001: $1500.00 USD (tax: $120.00 USD)
Order ORD-002: $3250.50 USD (tax: $260.04 USD)
Order ORD-003: $890.25 USD (tax: $71.22 USD)

=== Summary ===
Pipeline: E-Commerce Analytics
Processed: 3 orders
Capacity: 3 / 1000000

❓ Perguntas Frequentes

P: Qual devo usar, var ou final? R: Se a variável não será reatribuída, prefira final. Se precisar modificá-la, use var. A regra de lint oficial do Dart prefer_final_locals recomenda priorizar final.

P: Qual a diferença entre const e final? R: const é uma constante em tempo de compilação; seu valor deve ser determinado em tempo de compilação. final é uma constante em tempo de execução; pode ser atribuída apenas uma vez, mas seu valor pode ser computado em runtime. DateTime.now() não pode ser const.

P: Quando devo usar late? R: Use late quando uma variável não pode ser inicializada no ponto da declaração, mas você pode garantir que será inicializada antes do uso. Cenários comuns incluem injeção de dependência e configuração pós-construção. Uso incorreto levará a um LateInitializationError em runtime.

P: Qual a diferença entre dynamic e Object?? R: dynamic desliga toda verificação de tipo; o compilador não verifica nenhuma chamada de método. Object? retém a verificação de tipo; você só pode chamar métodos de Object. Prefira Object? quando precisar de flexibilidade.

P: O int do Dart é o mesmo na Web e na VM? R: Não exatamente. Na Dart VM, int é um inteiro de 64 bits. Quando compilado para JS, int está sujeito às limitações do JS Number (precisão de 53 bits). Tenha cautela com aritmética de números grandes.

P: Posso usar aspas simples ou aspas duplas para String? R: Ambas são aceitas e têm exatamente o mesmo efeito. O guia de estilo oficial do Dart recomenda aspas simples, usando aspas duplas apenas quando a string em si contém aspa simples.

P: Quando devo usar o tipo num? R: Use num quando precisar que um parâmetro ou variável aceite tanto int quanto double. num é o supertipo de int e double e suporta operações aritméticas básicas.


📖 Resumo


📝 Exercícios

  1. Básico (Dificuldade ⭐): Declare as seguintes variáveis: um nome de aplicação const, um horário atual final e um contador var. Imprima seus valores e tipos respectivamente.
  2. Intermediário (Dificuldade ⭐⭐): Escreva uma função que aceite um parâmetro do tipo num e retorne uma string formatada em USD desse número (ex.: formatUSD(1500.5) retorna "$1,500.50 USD"). Trate tanto entradas int quanto double.
  3. Desafio (Dificuldade ⭐⭐⭐): Projete uma classe Config que use late para inicializar preguiçosamente uma string de conexão de banco de dados, use const para definir valores padrão e use final para armazenar configuração lida de variáveis de ambiente. Demonstre a colaboração dessas três formas de declaração.

← Aula Anterior | Próxima Aula →

Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%