Dart: Variáveis e Tipos de Dados no Dart
Última atualização: 2026-08-26
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á
- Comparação dos cinco métodos de declaração: var / final / const / late / dynamic
- Tipos integrados: int / double / String / bool / num
- Melhores práticas para inferência de tipos e anotação explícita
- Interpolação de strings e strings de múltiplas linhas (triplas aspas + prefixo r)
- Cenário do Bob: Design de variáveis de configuração no DataPipeline
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 alterava seus tipos no meio do caminho. Durante uma refatoração, 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 livre ao mais restrito: 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 adequadamente permite que o compilador ajude você a encontrar bugs.
// 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
> **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
- O compilador detecta erros de tipo durante a compilação, evitando crashes em tempo de execução.
- Variáveis
constpermitem que o compilador otimize o desempenho. finalprevine modificação acidental, tornando a intenção do código mais clara.
3. Cinco Métodos de Declaração
(1) Árvore de Decisão de Métodos de Declaração
graph LR
subgraph Declarações
A[var] --> B[Inferência de tipo]
C[final] --> D[Constante em tempo de execução]
E[const] --> F[Constante em tempo de compilação]
G[late] --> H[Inicialização preguiçosa]
I[dynamic] --> J[Tipo dinâmico]
end
subgraph Tipos Integrados
K[int] --- L[double]
M[String] --- N[bool]
end
> **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
> **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
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 o tipo
// count = 'two thousand'; // Erro de compilação!
}
> **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
> **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
void main() {
// Definida uma vez em tempo de execução
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
}
> **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
> **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
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 imutáveis em profundidade
const List<String> formats = ['json', 'csv', 'html'];
// formats.add('xml'); // Erro! Não pode modificar lista const
// Construtor const
const config = PipelineConfig(batchSize: 10000);
}
> **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
> **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
class DataPipeline {
late String outputPath; // Será definido depois
void configure(String path) {
outputPath = path;
}
late final int maxRecords = _loadMaxRecords(); // Calculado no primeiro acesso
int _loadMaxRecords() {
print('Carregando configuração de max records...');
return 1000000;
}
}
> **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
> **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
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 tempo de execução
// Prefira Object? em vez de dynamic quando precisar de flexibilidade
Object? safeValue = 'test';
// safeValue.nonExistentMethod(); // Erro de compilação - mais seguro
}
> **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 dos Cinco Métodos de Declaração
| Método 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 tempo de execução | Imutável | Na declaração ou no construtor | Alta | Configuração em tempo de execução, 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 inicialização adiada |
dynamic |
Tempo de execução | Mutável | A qualquer momento | Baixa | Parsing de JSON, interoperabilidade |
4. Tipos Integrados em Detalhes
(1) Tipos Numéricos
▶ Exemplo
> **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
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 é par, true)
print(orderCount.clamp(0, 1000)); // 1000 (limitado ao máximo)
}
> **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 bits (varia no JS) | Contagem, indexação |
double |
64 bits IEEE 754 | Valores, proporções |
num |
Supertipo de int + double | Valores numéricos gerais |
(2) Tipo String
▶ Exemplo
> **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
void main() {
// Interpolação de strings
String product = 'DataPipeline';
int users = 5000;
print('$product tem $users usuários'); // Interpolação simples
print('Receita: ${users * 99} USD'); // Interpolação com expressão
print('Média: ${(125000 / users).toStringAsFixed(2)} USD');
// Strings de múltiplas linhas
String description = '''
DataPipeline - Ferramenta de Análise de E-Commerce
Processa até 1.000.000 pedidos por lote
Suporta formatos de saída JSON, CSV e HTML
''';
// 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'
}
> **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 com expressão | ${expr} |
'${a + b}' |
| Strings de múltiplas linhas | '''...''' |
Triplas aspas |
| Raw strings | r'...' |
r'\n' permanece como está |
(3) Tipo bool
▶ Exemplo
> **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
void main() {
bool isProduction = true;
bool isDebug = false;
// Dart exige bool explícito em condições
int count = 0;
// if (count) {} // Erro! Deve ser bool
if (count > 0) { // OK - comparação explícita
print('Tem registros');
}
// Operadores lógicos
bool shouldProcess = isProduction && !isDebug;
bool hasData = count > 0 || isProduction;
}
> **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
// 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
> **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
> **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
// Constantes de configuração do DataPipeline
const String appName = 'DataPipeline';
const int defaultBatchSize = 10000;
const double defaultTaxRate = 0.08;
// Configuração em tempo de execução
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 | Lote: $batchSize | Formato: $outputFormat';
}
> **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
// ============================================
// Demo de Declaração de Variáveis do DataPipeline
// Mostra o 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 em tempo de execução após construção
final double amount; // Constante em tempo de execução após construção
late String status; // Será definida 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 iniciado em $startTime');
}
void processOrder(Order order) {
processedCount++;
order.status = 'processed';
print('Pedido ${order.id}: ${order.formattedAmount} '
'(imposto: \$${order.tax.toStringAsFixed(2)} USD)');
}
void printSummary() {
print('\n=== Resumo ===');
print('Pipeline: $name');
print('Processados: $processedCount pedidos');
print('Capacidade: $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();
}
> **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:
DataPipeline iniciado em 2024-01-15 10:30:00.000
Pedido ORD-001: $1500.00 USD (imposto: $120.00 USD)
Pedido ORD-002: $3250.50 USD (imposto: $260.04 USD)
Pedido ORD-003: $890.25 USD (imposto: $71.22 USD)
=== Resumo ===
Pipeline: E-Commerce Analytics
Processados: 3 pedidos
Capacidade: 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, usevar. A regra de lint oficial do Dartprefer_final_localsrecomenda priorizarfinal.
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; só pode ser atribuída uma vez, mas seu valor pode ser calculado em tempo de execução.DateTime.now()não pode serconst.
P: Quando devo usar late? R: Use
latequando uma variável não pode ser inicializada no ponto de 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 umLateInitializationErrorem tempo de execução.
P: Qual a diferença entre dynamic e Object?? R:
dynamicdesliga toda verificação de tipos; o compilador não verifica nenhuma chamada de método.Object?mantém a verificação de tipos; você só pode chamar métodos deObject. PrefiraObject?quando precisar de flexibilidade.
P: O int do Dart é o mesmo na Web e na VM? R: Não exatamente. Na VM do Dart,
inté um inteiro de 64 bits. Quando compilado para JS,intestá 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 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 uma aspa simples.
P: Quando devo usar o tipo num? R: Use
numquando precisar que um parâmetro ou variável aceite tantointquantodouble.numé o supertipo deintedoublee suporta operações aritméticas básicas.
📖 Resumo
- Cinco métodos de declaração do mais restrito ao mais livre: const → final → var → late → dynamic
consté determinado em tempo de compilação,finalé determinado em tempo de execução mas atribuído apenas uma vez,varé mutável e infere o tipo- Tipos integrados:
int(inteiro),double(ponto flutuante),String(string + interpolação),bool(booleano) - Use
var/finalpara inferência de variáveis locais; anote tipos explicitamente para APIs públicas - O DataPipeline usa
constpara definir constantes de configuração,finalpara definir valores imutáveis em tempo de execução
📝 Exercícios
- Básico (Dificuldade ⭐): Declare as seguintes variáveis: um nome de aplicação
const, um horário atualfinal, e um contadorvar. Imprima seus valores e tipos respectivamente. - Intermediário (Dificuldade ⭐⭐): Escreva uma função que aceita um parâmetro do tipo
nume retorna uma string formatada em USD desse número (ex:formatUSD(1500.5)retorna"$1,500.50 USD"). Trate tanto entradasintquantodouble. - Avançado (Dificuldade ⭐⭐⭐): Design uma classe
Configque usalatepara inicializar preguiçosamente uma string de conexão de banco de dados, usaconstpara definir valores padrão, e usafinalpara armazenar configuração lida de variáveis de ambiente. Demonstre a colaboração desses três métodos de declaração.