Variáveis e Tipos
Declaração de variáveis
Em Dart, existem várias formas de declarar variáveis:
var
A palavra-chave var permite que o tipo seja inferido automaticamente pelo compilador:
var nome = "João"; // tipo String
var idade = 25; // tipo int
var altura = 1.75; // tipo double
Tipos explícitos
Você pode declarar o tipo explicitamente:
String nome = "João";
int idade = 25;
double altura = 1.75;
bool isAtivo = true;
final
A palavra-chave final cria uma variável que só pode ser atribuída uma vez. O valor não pode ser alterado após a atribuição inicial:
final nome = "João";
final int idade = 25;
// nome = "Maria"; // Erro! Não é possível alterar uma variável final
const
A palavra-chave const cria uma constante em tempo de compilação. O valor deve ser conhecido em tempo de compilação:
const pi = 3.14159;
const String nome = "João";
const lista = [1, 2, 3];
// const agora = DateTime.now(); // Erro! DateTime.now() não é conhecido em tempo de compilação
Diferença entre final e const: final pode ser atribuído em tempo de execução, enquanto const deve ser conhecido em tempo de compilação.
late
A palavra-chave late permite declarar uma variável não-nula que será inicializada posteriormente:
late String nome;
void inicializar() {
nome = "João"; // Inicialização posterior
print(nome);
}
late é útil quando você sabe que a variável será inicializada antes de ser usada, mas não no momento da declaração.
Null safety
Dart possui um sistema robusto de null safety que previne erros comuns relacionados a valores nulos. Por padrão, variáveis não podem ser nulas:
String nome = "João";
// nome = null; // Erro! String não pode ser nula
Para permitir valores nulos, use o operador ?:
String? nome; // Pode ser null
nome = null; // OK
nome = "João"; // OK
Ao trabalhar com variáveis nullable, você precisa verificar se são nulas antes de usar:
String? nome;
if (nome != null) {
print(nome.length); // OK, nome não é null aqui
}
// Ou use o operador null-aware
print(nome?.length); // Retorna null se nome for null
print(nome?.length ?? 0); // Retorna 0 se nome for null
Default values
Variáveis não inicializadas têm valores padrão:
int? numero; // null
int numero2 = 0; // 0
String? texto; // null
bool? flag; // null
List? lista; // null
Tipos de dados
Numbers
Dart possui dois tipos numéricos:
int: Números inteiros
int idade = 25;
int negativo = -10;
int hex = 0xFF; // Hexadecimal
int binario = 0b1010; // Binário
double: Números de ponto flutuante
double altura = 1.75;
double pi = 3.14159;
double exponencial = 1.2e5; // 120000.0
Ambos são subclasses de num:
num valor = 10; // Pode ser int ou double
valor = 10.5; // OK
Strings
Strings podem ser criadas com aspas simples ou duplas:
String nome1 = 'João';
String nome2 = "Maria";
String interpolation: Você pode inserir expressões dentro de strings:
String nome = "João";
int idade = 25;
String mensagem = "Olá, meu nome é $nome e tenho $idade anos";
String calculo = "O dobro de $idade é ${idade * 2}";
Multiline strings: Use três aspas para strings de múltiplas linhas:
String texto = '''
Esta é uma string
de múltiplas linhas
muito útil para textos longos
''';
Booleans
O tipo bool representa valores verdadeiro ou falso:
bool isAtivo = true;
bool isInativo = false;
if (isAtivo) {
print("Está ativo");
}
Lists
Listas são coleções ordenadas de elementos:
List<int> numeros = [1, 2, 3, 4, 5];
List<String> nomes = ['João', 'Maria', 'Pedro'];
// Lista vazia
List<int> vazia = [];
// Adicionar elementos
numeros.add(6);
numeros.addAll([7, 8, 9]);
// Acessar elementos
print(numeros[0]); // 1
print(numeros.length); // 9
// Lista fixa (não pode adicionar/remover)
List<int> fixa = List.filled(3, 0); // [0, 0, 0]
Maps
Maps são coleções de pares chave-valor:
Map<String, int> idades = {
'João': 25,
'Maria': 30,
'Pedro': 28
};
// Acessar valores
print(idades['João']); // 25
// Adicionar ou atualizar
idades['Ana'] = 22;
idades['João'] = 26;
// Verificar se contém chave
if (idades.containsKey('Maria')) {
print("Maria está no mapa");
}
// Iterar sobre o mapa
idades.forEach((nome, idade) {
print('$nome tem $idade anos');
});
Enums
Enums definem um conjunto fixo de valores constantes:
enum Status {
pendente,
emAndamento,
concluido,
cancelado
}
Status tarefa = Status.pendente;
if (tarefa == Status.pendente) {
print("Tarefa ainda não iniciada");
}
// Acessar valores do enum
print(Status.values); // [Status.pendente, Status.emAndamento, ...]
print(tarefa.name); // "pendente"
Enums com propriedades: Enums podem ter propriedades e métodos associados:
enum Prioridade {
baixa('Baixa', 1),
media('Média', 2),
alta('Alta', 3);
final String descricao;
final int nivel;
const Prioridade(this.descricao, this.nivel);
bool get isUrgente => nivel >= 3;
String get mensagem => 'Prioridade $descricao (nível $nivel)';
}
Prioridade tarefa = Prioridade.alta;
print(tarefa.descricao); // "Alta"
print(tarefa.nivel); // 3
print(tarefa.isUrgente); // true
print(tarefa.mensagem); // "Prioridade Alta (nível 3)"
Este exemplo mostra um enum com múltiplas propriedades (descricao, nivel), um constructor que inicializa essas propriedades, e métodos getter (isUrgente e mensagem) que calculam valores baseados nas propriedades.
Object
Tudo em Dart é um objeto, incluindo números, funções e null:
Object qualquer = "texto";
qualquer = 42;
qualquer = true;
Exercícios
-
Declaração de variáveis: Crie variáveis usando
var, tipos explícitos,finaleconst. Demonstre a diferença entre elas tentando reatribuir valores. -
Null safety: Crie uma função que receba um
String?(nullable) e retorne o comprimento da string. Se a string fornull, retorne 0. Use operadores null-aware. -
Tipos de dados: Crie um programa que demonstre o uso de
int,double,String,bool,ListeMap. Inclua operações como adicionar elementos a listas e atualizar valores em maps. -
String interpolation: Crie uma função que receba nome, idade e cidade, e retorne uma string formatada usando interpolação: "Olá, meu nome é [nome], tenho [idade] anos e moro em [cidade]".
-
Enums: Crie um enum
StatusTarefacom valorespendente,emAndamento,concluidaecancelada. Crie uma função que receba um status e retorne uma mensagem descritiva.
Soluções
Ver solução do exercício 1
void main() {
// var - tipo inferido
var nome = "João";
nome = "Maria"; // OK
// Tipo explícito
int idade = 25;
idade = 26; // OK
// final - atribuído uma vez
final sobrenome = "Silva";
// sobrenome = "Santos"; // Erro! Não pode reatribuir
// const - constante em tempo de compilação
const pi = 3.14159;
// pi = 3.14; // Erro! Não pode reatribuir
print("Nome: $nome, Idade: $idade, Sobrenome: $sobrenome, PI: $pi");
}
Ver solução do exercício 2
int obterComprimento(String? texto) {
return texto?.length ?? 0;
}
void main() {
print(obterComprimento("Dart")); // 4
print(obterComprimento(null)); // 0
// Alternativa usando if
int obterComprimento2(String? texto) {
if (texto != null) {
return texto.length;
}
return 0;
}
print(obterComprimento2("Flutter")); // 7
print(obterComprimento2(null)); // 0
}
Ver solução do exercício 3
void main() {
// int
int idade = 25;
int anoNascimento = 1998;
// double
double altura = 1.75;
double peso = 70.5;
// String
String nome = "João";
String sobrenome = "Silva";
// bool
bool isAtivo = true;
bool temPermissao = false;
// List
List<String> frutas = ['maçã', 'banana'];
frutas.add('laranja');
frutas.addAll(['uva', 'manga']);
print("Frutas: $frutas");
// Map
Map<String, int> idades = {
'João': 25,
'Maria': 30,
};
idades['Pedro'] = 28;
idades['João'] = 26; // Atualiza valor
print("Idades: $idades");
// Operações
print("Idade atual: $idade");
print("Altura: $altura metros");
print("Nome completo: $nome $sobrenome");
print("Ativo: $isAtivo, Permissão: $temPermissao");
}
Ver solução do exercício 4
String apresentar(String nome, int idade, String cidade) {
return "Olá, meu nome é $nome, tenho $idade anos e moro em $cidade";
}
void main() {
String mensagem = apresentar("João", 25, "São Paulo");
print(mensagem);
// Com cálculos na interpolação
String apresentarComCalculo(String nome, int anoNascimento, String cidade) {
int idade = DateTime.now().year - anoNascimento;
return "Olá, meu nome é $nome, tenho $idade anos e moro em $cidade";
}
print(apresentarComCalculo("Maria", 1995, "Rio de Janeiro"));
}
Ver solução do exercício 5
enum StatusTarefa {
pendente,
emAndamento,
concluida,
cancelada
}
String obterMensagemStatus(StatusTarefa status) {
switch (status) {
case StatusTarefa.pendente:
return "A tarefa está aguardando início";
case StatusTarefa.emAndamento:
return "A tarefa está em andamento";
case StatusTarefa.concluida:
return "A tarefa foi concluída";
case StatusTarefa.cancelada:
return "A tarefa foi cancelada";
}
}
void main() {
StatusTarefa status = StatusTarefa.emAndamento;
print(obterMensagemStatus(status));
// Iterar sobre todos os status
for (var s in StatusTarefa.values) {
print("${s.name}: ${obterMensagemStatus(s)}");
}
}