O sistema de tipos en Dart #
Dart é unha linguaxe con tipado estático e seguro (sound typing), o que significa que tenta garantir que os valores sempre coincidan co tipo declarado, tanto en tempo de compilación como en tempo de execución.
✅ Que significa “tipado seguro” (sound typing)? #
- Erro en tempo de compilación se usas tipos incorrectos (ex: asignar un
String
a unint
). - Erro en tempo de execución se un cast explícito falla (ex:
object as String
e non é unString
). - Tipos obrigatorios pero non ten que ser sempre explícitos, xa que Dart pode inferir tipos automaticamente.
📍 Exemplo: Erro por inferencia incorrecta #
void printInts(List<int> a) => print(a);
void main() {
var lista = [];
lista.add(1);
lista.add('2'); // ❌ engadimos un String
printInts(lista); // Erro: List<dynamic> non é List<int>
}
✅ Solución: indicar o tipo da lista ao inicializala:
void main() {
var lista = <int>[];
lista.add(1);
lista.add(2);
printInts(lista); // Correcto
}
🛠 Boas prácticas e regras útiles #
🧪 Retornos e parámetros con tipos correctos #
- Ao sobrescribir métodos, o tipo de retorno pode ser un subtipo.
- Os parámetros non se poden restrinxir máis, só ampliar ou manter.
class Animal {
Animal get parent => Animal();
void chase(Animal a) {}
}
class Gato extends Animal {
@override
Gato get parent => Gato(); // ✅ retorno máis específico
@override
void chase(Object a) {} // ✅ parámetro máis xeral
}
🔥 Erros en tempo de execución por cast incorrecto #
int asumeString(dynamic obxecto) {
String texto = obxecto; // ❌ pode fallar se non é String
return texto.length;
}
void main() {
print(asumeString(1)); // TypeError en tempo de execución
}
📌 Conclusión #
O sistema de tipos en Dart axuda a detectar erros antes de que sucedan, escribir código máis seguro e aproveitar mellor o compilador.
🔎 Máis información #
Non incluín toda a información sobre este punto, xa que excede os contidos que precisamos para o módulo de PMDM.
Se queres afondar máis, podes consultar a documentación oficial de Dart sobre o sistema de tipos:
👉 https://dart.dev/language/type-system
🧠 Patróns en Dart (Pattern Matching e Desestruturación) #
🔒 Os patróns en Dart están dispoñibles a partir da versión 3.0 do idioma.
Os patróns permiten comprobar e extraer valores dunha estrutura de datos de forma clara e concisa. A esta técnica tamén se lle chama desestruturación (destructuring).
📌 Para que serven os patróns? #
- Saber se un valor ten unha certa forma (por exemplo: é unha lista? un mapa? ten 2 elementos?).
- Ver se un valor coincide cunha constante.
- Extraer datos de estruturas compostas como listas, mapas, rexistros ou obxectos.
- Declarar variables a partir dos valores extraídos.
📍 Onde se poden usar patróns? #
- Declaracións de variables:
var (a, b) = (1, 2);
- Asignacións:
(x, y) = (y, x);
- Condicións con
switch
ouif-case
- Bucles
for
efor-in
✅ Exemplos básicos #
🟨 Desestruturación de tuplas (records) #
void main() {
var (nome, idade) = ('Diego', 44);
print('$nome ten $idade anos'); // Diego ten 44 anos
}
🔄 Intercambiar variables sen variable temporal #
void main() {
var a = 'esquerda';
var b = 'dereita';
(a, b) = (b, a);
print('$a - $b'); // dereita - esquerda
}
📋 Patróns en listas #
void main() {
var lista = [1, 2, 3];
var [a, b, c] = lista;
print(a + b + c); // 6
}
🗺️ Patróns en mapas #
void main() {
var datos = {'usuario': ['Lúa', 15]};
switch (datos) {
case {'usuario': [String nome, int idade]}:
print('Usuario $nome ten $idade anos');
break;
default:
print('Datos non válidos');
}
}
🧪 Uso en switch
para comprobar tipos ou valores #
void main() {
var valor = 3;
switch (valor) {
case 1:
print('Un');
case >= 2 && <= 4:
print('Entre dous e catro');
default:
print('Outro número');
}
}
🔄 Uso en bucles for-in
con mapas #
void main() {
var hist = {'a': 10, 'b': 5};
for (var MapEntry(:key, :value) in hist.entries) {
print('$key apareceu $value veces');
}
}
🧠 Conclusión #
Os patróns fan que o código sexa máis conciso, expresivo e seguro, especialmente cando traballamos con estruturas complexas ou precisamos validar datos. Son unha ferramenta moi potente, pero recomendada para alumnado cun certo dominio previo de Dart.
🧪 CodeLab #
Un CodeLab é un tutorial práctico e guiado que che permite aprender un concepto mentres escribes e executas código real paso a paso.
Se queres practicar o uso de patróns e desestruturación en Dart, podes seguir este codelab oficial:
👉 https://codelabs.developers.google.com/codelabs/dart-patterns-records
🔎 Máis información #
Non incluín toda a información sobre este punto, xa que excede os contidos que precisamos para o módulo de PMDM.
Se queres afondar máis, podes consultar a documentación oficial de Dart sobre os patróns na documentación oficial de Dart:
👉 https://dart.dev/language/patterns
🏷️ Metadata en Dart #
En Dart, a metadata permite engadir información adicional ao teu código usando anotacións.
Unha anotación comeza co símbolo @
seguido do nome dunha constante de tempo de compilación ou dun constructor constante.
🔹 Anotacións dispoñibles por defecto #
Dart inclúe algunhas anotacións que podes usar en calquera código:
Anotación | Uso principal |
---|---|
@Deprecated | Marca algo como obsoleto e permite engadir unha mensaxe. |
@deprecated | Versión sen mensaxe (non recomendada). |
@override | Indica que se está sobrescribindo un método herdado. |
@pragma | Información especial para o compilador (uso avanzado). |
🔹 Exemplo co uso de @Deprecated
#
class Television {
/// Usa [turnOn] no seu lugar.
@Deprecated('Usa turnOn no canto deste método')
void activate() {
turnOn();
}
void turnOn() {
print('Televisor acendido');
}
}
🔍 @Deprecated
inclúe unha mensaxe explicativa.
Tamén podes usar @deprecated
sen mensaxe, pero non se recomenda.
🔹 Crear anotacións personalizadas #
Podes definir as túas propias anotacións creando unha clase const
.
Por exemplo, imos crear unha anotación @Todo
:
class Todo {
final String quen;
final String que;
const Todo(this.quen, this.que);
}
E así é como se usa:
@Todo('Dash', 'Implementar esta función')
void facerAlgo() {
print('Facendo algo...');
}
📌 Onde se pode usar metadata #
As anotacións poden colocarse antes de:
- clases, funcións, métodos, construtores, parámetros, variables
- importacións/exportacións
- typedefs, campos ou tipos xenéricos
📚 Para saber máis #
📦 Librarías e importacións en Dart #
Dart permite organizar o código en librarías para facelo máis modular, reutilizable e privado.
Cada arquivo Dart é unha libraría, mesmo se non inclúe a directiva library
.
🔹 Librarías e privacidade #
As librarías en Dart tamén son unha unidade de privacidade:
os identificadores que comezan por guión baixo _
só son accesibles desde dentro da mesma libraría.
🔍 Dart non usa
public
,private
ouprotected
como outras linguaxes, senón que controla o acceso a través do uso de_
e da organización en librarías.
🔹 Importar librarías #
Usamos import
para facer accesibles elementos doutro arquivo ou paquete.
import 'dart:math'; // Libraría estándar
import 'package:test/test.dart'; // Libraría dun paquete externo
import 'lib/utilidades.dart'; // Arquivo local
dart:
→ librarías propias de Dart (core SDK).package:
→ paquetes externos xestionados con pub.- rutas relativas → arquivos locais do proxecto.
🔹 Prefixos para evitar conflitos #
Se importas dúas librarías que teñen o mesmo identificador, podes usar prefixos:
import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;
Element e1 = Element(); // da lib1
lib2.Element e2 = lib2.Element(); // da lib2
🔹 Importacións selectivas #
Podes importar só partes dunha libraría ou excluír nomes concretos:
import 'package:lib1/lib1.dart' show foo; // Só importa 'foo'
import 'package:lib2/lib2.dart' hide foo; // Importa todo excepto 'foo'
📚 Principais librarías estándar de Dart #
Libraría | Descrición |
---|---|
dart:core | Inclúe tipos e funcións básicos (String, int, etc.) |
dart:math | Funcións matemáticas e constantes |
dart:io | Entrada/saída para scripts ou apps de consola |
dart:convert | Conversión de datos (JSON, UTF-8, Base64…) |
dart:async | Futures, Streams e programación asíncrona |
dart:collection | Estruturas de datos avanzadas (Mapas, Set, etc.) |
dart:js_interop | Interoperabilidade con JavaScript en apps web |
🔗 Máis información #
Para aprender máis sobre librarías,
import
, paquetes e xestión de código en Dart:
🔄 Concorrencia en Dart #
Dart permite escribir programas que executan varias tarefas ao mesmo tempo sen bloquear a interface de usuario nin deter a execución do resto do código. Isto é especialmente útil en aplicacións que acceden a redes, ficheiros, bases de datos ou realizan operacións lentas.
🔹 Programación asíncrona con async
e await
#
A principal forma de xestionar a concorrencia en Dart é mediante funcións asíncronas, usando as palabras clave:
async
: marca unha función como asíncrona.await
: suspende a execución ata que unha operación se complete (por exemplo, unha petición á rede ou unha lectura de ficheiro).
Desta forma, Dart mantén unha experiencia fluída, especialmente en interfaces gráficas.
🔹 Future
e Stream
#
- Un
Future
representa unha operación que rematará no futuro e devolverá un resultado (ou erro). - Un
Stream
representa unha serie de valores asincrónicos (como eventos ou paquetes de datos).
🔹 Isolates #
Dart é single-threaded por defecto, pero permite executar código en paralelo usando isolates, que son como pequenos procesos independentes. Cada isolate ten o seu propio espazo de memoria, o que evita condicións de carreira (race conditions).
Úsanse en casos onde se require cálculo intensivo ou tarefas que non poden compartir memoria.
🔗 Para saber máis #
Se queres afondar na concorrencia e programación asíncrona en Dart, podes consultar:
🚫 Sound null safety #
Dart incorpora un sistema chamado sound null safety, que evita erros comúns provocados polo uso de valores nulos de forma inesperada.
🔹 Que é null safety? #
O null safety axuda a previr erros que ocorren cando se accede a variables que conteñen null
, pero que non deberían.
Con null safety:
- Todas as variables deben inicializarse cun valor non nulo por defecto.
- Unha variable non pode conter
null
, agás que o tipo se defina explicitamente como nullable.
🔗 Para saber máis #
📚 Librarías principais do núcleo de Dart #
Dart conta cun conxunto rico de librarías principais (core libraries) que proporcionan funcionalidade esencial para tarefas cotiás: coleccións, operacións matemáticas, codificación e decodificación de datos, programación asíncrona, entrada/saída, etc.
🔹 Principais librarías estándar #
Libraría | Descrición |
---|---|
dart:core | Tipos básicos (String, int, bool…), coleccións (List , Map , Set ) e máis. Esta libraría impórtase automaticamente. |
dart:async | Programación asíncrona con Future , Stream e outras utilidades. |
dart:math | Constantes e funcións matemáticas, xerador de números aleatorios, etc. |
dart:convert | Codificadores e decodificadores (JSON, UTF-8, Base64…). |
dart:io | Entrada/saída para apps de consola, servidores e apps Flutter (non dispoñible en web). |
dart:js_interop | Interoperabilidade co mundo web (substitúe a dart:html en contextos modernos). |
🧭 Outras categorías de librarías #
- Librarías multiplataforma: dispoñibles en todas as plataformas (web, escritorio, móbil, consola…).
- Librarías específicas de plataforma:
- 📱 Native: para apps Flutter ou scripts en Dart VM (
dart:io
,dart:isolate
…). - 🌐 Web: para apps que se executan no navegador (
dart:html
,dart:js_interop
…).
📌 Conclusión #
As librarías do núcleo de Dart cobren unha ampla gama de funcionalidades esenciais.
Se necesitas algo máis específico ou avanzado, tamén podes recorrer a paquetes externos dispoñibles en pub.dev, o xestor oficial de paquetes para Dart e Flutter.
🔹 Onde atopar máis información #
Estes apuntamentos ofrecen unha visión xeral. Para detalles máis específicos:
- 📘 Guía oficial das librarías principais →
- 📚 Referencia da API de Dart →
- 📦 Buscador de paquetes e documentación en pub.dev →
- 🌐 Guía de librarías para desenvolvedores web →
🌐 Outros temas importantes en Dart #
A continuación inclúense temas complementarios e recorrentes ao traballar con Dart, cada un cunha breve descrición e onde atopar información oficial para profundar.
🔸 Serialización JSON #
Permite converter obxectos de Dart a formato JSON e viceversa.
Moi útil para traballar con APIs ou gardar datos.
🔗 Guía oficial sobre JSON en Dart →
🔸 Representación numérica #
Dart fornece tipos e operacións para manipular números enteiros, decimais e binarios.
🔸 APIs de Google #
Dart e Flutter permiten acceder a servizos de Google como Google Drive, Calendar, Maps, etc., mediante paquetes dispoñibles en pub.dev.
🔸 Aplicacións multiplataforma #
Un dos puntos fortes de Dart con Flutter é o desenvolvemento de apps para Android, iOS, web, escritorio e consola cunha única base de código.
🔗 Guía oficial sobre apps multiplataforma →
🔸 Aplicacións de liña de comandos e servidor #
Pódense crear scripts, utilidades de consola ou servidores web usando Dart VM.
🔗 Guía para apps de consola e servidor →
🔸 Aplicacións web #
Dart tamén se pode compilar a JavaScript para crear apps que funcionen directamente no navegador.
🔗 Guía para apps web con Dart →
🔸 Declaracións de contorno (Environment declarations) #
Permiten definir variables de contorno que se poden ler en tempo de execución, moi útil para configuracións como dev
, prod
, etc.