🧮 Declaración e inicialización de variables. Inferencia de tipos #
En Dart, para declarar unha variable podes:
- Usar
var(Dart infire o tipo automaticamente) - Indicar directamente o tipo (
String,int, etc.) - Usar tipos máis xerais como
Objectoudynamic, se necesitas máis flexibilidade
✅ Exemplo básico con inferencia de tipos #
var nome = 'Diego';
Neste caso:
- Usamos
var - Dart infire que
nomeé de tipoString, porque o valor inicial é'Diego' - A partir dese momento,
nomesó poderá almacenar cadeas (String)
nome = 'Uxía'; // ✅ correcto
nome = 10; // ❌ erro: non é unha String
✅ Declaración explícita do tipo #
String nome = 'Diego';
Funciona igual que co var, pero o tipo está especificado claramente, o que mellora a lectura e o mantemento do código.
✅ Uso de Object #
Object dato = 'Diego';
Objecté o pai de tódolos obxectos en Dart.- Isto significa que pode almacenar calquera valor que sexa un obxecto:
int,String,bool,List, etc.
dato = 42; // ✅ permitido
dato = true; // ✅ permitido
dato = ['a', 'b']; // ✅ permitido
✅ Uso de dynamic #
dynamicpermite cambiar o tipo da variable en calquera momento.- Dart non comproba o tipo en tempo de compilación, polo hai que ter coidado xa que é posible facer cousas que poidan fallar en tempo de execución.
dynamic valor = 'Diego';
valor = 123;
valor = true;
valor = [1, 2, 3];
print(valor.nonExiste()); // ❌ Isto compilará, pero fallará ao executarse
🧠 Comparativa: var, Object, dynamic #
| Declaración | Pode cambiar de tipo? | Acceso a métodos? | Seguridade de tipos |
|---|---|---|---|
var nome = 'Ana' | ❌ Non | ✅ Si (de String) | ✅ Alta |
String nome = ... | ❌ Non | ✅ Si | ✅ Alta |
Object nome = ... | ✅ Si (pero restrinxido) | ❌ Precisa casting | ⚠️ Media |
dynamic nome = ... | ✅ Si (totalmente) | ✅ Sen restricións | ❌ Baixa |
✅ Recomendacións xerais #
- Usa
varcando o tipo é obvio e non cambiará. - Usa o tipo explícito (
String,int, etc.) cando queiras claridade. - Usa
Objectse necesitas flexibilidade pero queres algo de seguridade. - Usa
dynamicsó se realmente necesitas cambiar tipos, ou estás traballando con código moi xenérico.
🧪 Exemplo completo #
void main() {
var nome = 'Ana'; // infírese como String
String apelido = 'López'; // tipo especificado
Object idade = 30; // pode ser calquera obxecto
dynamic calquera = true; // pode ser calquera cousa
print(nome.toUpperCase()); // ✅
// print(idade.toUpperCase()); // ❌ erro
print((idade as int).isEven); // ✅ usando casting
print(calquera); // ✅
}
✅ Opcionais #
Dart implementa unha xestión fiable de valores nulos (sound null safety), o que significa que os erros por acceso a un null son detectados en tempo de compilación.
Para facer un tipo de dato opcional, engade ? ao tipo para permitir que sexa null ou que teña calquera valor do tipo:
String? apelido = null; // Variable opcional (pode conter null ou un String)
apelido = "Rodicio"; // Reasígnase un valor de tipo String
🧭 Valor por defecto #
En Dart, todas as variables opcionais teñen por defecto o valor null, a non ser que se inicialicen explicitamente.
Mesmo tipos como int, double, bool ou String poden ser null, pero só se se declaran como opcionais, porque Dart emprega o sistema de null safety (seguridade contra nulos) e todo é un obxecto, mesmo os números.
Así, por exemplo:
int? idade;
print(idade); // imprime: null
Neste caso:
- Declaramos unha variable
idadede tipoint?, é dicir, un enteiro que pode ser nulo. - Como non lle damos ningún valor, Dart lle asigna automaticamente
null.
📌 Nota:
- A non ser que sexa un tipo opcional, non podemos asignar
nulldirectamente.- Así, por exemplo, se facemos
int numero = null;daría un erro en tempo de compilación:
int numero = null; // ❌ Erro: non se pode asignar null a un tipo non opcional
Se queremos declarar unha variable non opcional sen inicializala de inmediato, podemos usar late:
late int numero;
numero = 42; // ✅ Permitido
🚫 Tipos non opcionais #
Se declaras unha variable non opcional (por defecto), Dart obrígache a inicializala antes de usala. Se non o fas, dará erro en tempo de compilación.
int contador;
print(contador); // ❌ Erro: a variable non foi inicializada
✅ Solución:
int contador = 0;
print(contador); // 0
✅ Asignación condicional #
A seguinte estrutura é válida porque Dart asegura que a variable será inicializada en todos os casos posibles antes de usarse:
int lineas;
if (modoResumo) {
lineas = 10;
} else {
lineas = 0;
}
print(lineas); // ✅ Correcto, Dart sabe que sempre se inicializa
🧠 Resumo #
| Declaración | Inicialización obrigatoria? | Valor por defecto |
|---|---|---|
int contador; | ✅ Si | ❌ Erro se non se inicializa |
int? contador; | ❌ Non | ✅ null |
var nome = 'Ana' | ✅ Si (inferencia) | — |
✅ Recomendación #
- Se non sabes o valor inicial, usa tipos opcionais (
int?,String?…) ou inicializa con valores por defecto (= 0,= '', etc.). - Usa
latese garantes que a variable se inicializará antes de usarse (ver seguinte punto).
🕓 Variables late #
O modificador late permite:
- Declarar variables non opcionais que se inicializan máis tarde.
- Inicializar variables só cando se usan por primeira vez.
/*
• Declárase unha variable descrición de tipo String, que non é opcional.
• Como non se lle dá valor nese momento, Dart esixiría un erro… a non ser que uses late.
• late di: “Confía en min, prometo que lle darei un valor antes de usala”.
*/
late String descricion;
void main() {
descricion = 'Almendrados!';
print(descricion);
/*
• A variable recibe un valor antes de usarse, así que non hai erro.
• Se intentas usala sen inicializar, Dart lanzaría un erro en tempo de execución.
*/
}
late String temperatura = lerTermometro(); // execútase só se se usa
/*
• Aquí tamén se usa late, pero con inicialización directa.
• Isto significa que a función lerTermómetro() non se executará ata que alguén use a variable temperatura por primeira vez.
• É unha forma de facer inicialización “vaga” (lazy initialization), útil cando:
• A operación é custosa (ex: ler dun sensor ou disco).
• Pode que nunca se necesite ese valor.
*/
⚠️ Se accedes a unha variable
latesen inicializala, Dart lanza un erro en tempo de execución.
🔐 final e const #
Se non pensas modificar o valor dunha variable, usa final ou const.
final: #
Unha variable final pode obter o seu valor en tempo de execución, pero non pode cambiar despois de asignarse.
final data = DateTime.now(); // valor calculado no momento
print(data); // correcto
data = DateTime.utc(2024); // ❌ Erro: non se pode reasignar
Tamén se pode usar con tipo explícito:
final String nome = 'Diego';
const: #
Unha variable const debe conter un valor coñecido en tempo de compilación.
const pi = 3.1416;
const String saudo = 'Ola mundo';
const lista = [1, 2, 3]; // lista inmutable
Se usas const con obxectos complexos, son completamente inmutables:
const usuario = {'nome': 'Ana', 'idade': 30};
// usuario['idade'] = 31; // ❌ Erro: os campos dun const non poden cambiar
📌 Comparativa rápida #
| Característica | final | const |
|---|---|---|
| Reasignación | ❌ Non | ❌ Non |
| Valor fixo necesario | ✅ Si (unha vez) | ✅ Si (en tempo de compilación) |
| Pode calcularse | ✅ Si (ex. DateTime.now()) | ❌ Non (só valores coñecidos) |
| Obxecto mutable | ✅ Si (o obxecto si pode cambiar) | ❌ Non (todo o obxecto é inmutable) |
📌
constrequire que o valor sexa coñecido en tempo de compilación.📌
finalpermite valores calculados en execución, pero que non poden cambiar despois.
❔ Variables comodín (_) #
Dende Dart 3.7, podes usar o carácter subliñado _ para declarar variables locais non vinculantes (wildcards), que se ignoran. Vexamos tres exemplos de uso:
/*
• Aquí créanse dúas variables locais chamadas _, que conteñen valores.
• A pesar de ter o mesmo nome, Dart permíteo porque _ é tratado como non vinculante.
• É útil cando só precisas executar unha expresión ou inicializar algo, pero non necesitas acceder ao valor despois.
*/
var _ = 1;
int _ = 2;
/*
• Este bucle percorre lista, pero como non necesitas o valor de cada elemento, usas _ como comodín.
• Exemplo típico cando só che interesa repetir unha acción n veces, sen importar o contido.
*/
for (var _ in lista) {}
/*
Aquí usas _ como parámetro do catch, porque non necesitas o obxecto da excepción, só queres xestionar o erro.
• Equivalente a dicir: “non me importa que tipo de erro foi, só quero reaccionar”.
*/
try {
throw 'erro!';
} catch (_) {
print('Oops!');
}
💡 Consello: usa
_para variables temporais que non precises empregar. Dart admite múltiples_no mesmo ámbito sen erros de colisión.