- 🏷️ typedef: poñer nome a un tipo
- 🧪 Crear elementos xenéricos
- 🧩 Patróns e desestruturación
- 🔎 Comprobar tipos con is e as
- 🌱 Xeradores
- 🔄 Outras formas de usar Future e Stream
- ⚙️ Isolates e bucle de eventos
- 🧰 Máis operacións con coleccións
- ➕ Outros operadores e instrucións
- 🕓 Inicialización aprazada e valores ignorados
- 🔣 Unicode e paquetes
- 📚 Importacións e anotacións
- 🖥️ Argumentos de main
Estes apartados son de ampliación e consulta. Non precisamos dominar todas estas variantes para comezar con Flutter.
🏷️ typedef: poñer nome a un tipo
Un alias dá un nome máis cómodo a un tipo existente; non crea un tipo novo. Por exemplo, podemos poñer nome ao tipo dun callback. En Flutter atoparemos alias como VoidCallback.
🔗 Ver o código en DartPad — https://dartpad.dev/?id=33e80e89a3a5aa835bd99b6ac2079c65
📚 Documentación de typedef — https://dart.dev/language/typedefs.
🧪 Crear elementos xenéricos
Xa usamos xenéricos en List<String> ou Future<String>. Tamén podemos definir unha clase que traballe cun tipo indicado ao usala. Este exemplo é para volver a el despois das clases e dos construtores do Tema 2.2.
🔗 Ver o código en DartPad — https://dartpad.dev/?id=cf17c04184d9043c1016821290e9d48b
📚 Documentación de xenéricos — https://dart.dev/language/generics.
🧩 Patróns e desestruturación
Un patrón permite comprobar a forma dun dato e extraer partes del. A desestruturación garda esas partes en variables. Pódese usar con rexistros, listas, mapas ou nun switch. if-case executa un bloque cando o dato encaixa nun patrón.
final director = (nome: 'Diego Rodicio', cargo: 'Director');
final (nome: nome, cargo: cargo) = director; // Extraemos os dous campos.
print('$nome: $cargo');
📚 Patróns — https://dart.dev/language/patterns e if-case — https://dart.dev/language/branches#if-case.
🔎 Comprobar tipos con is e as
Xa vimos Object e dynamic no apartado de variables. Para traballar cun dato de tipo xeral podemos comprobar que tipo de valor contén.
iscomproba o tipo. Dentro dunif, Dart pode usar esa información para permitir operacións dese tipo.asesixe que o valor sexa compatible co tipo indicado (cast). Se non o é, falla ao executar. Non transforma un texto nun número; para iso usamosparse()outryParse().
Object dato = 'Diego';
if (dato is String) {
print(dato.toUpperCase()); // Aquí Dart sabe que é un String.
}
// '8' as int fallaría: ese valor é un texto, non un int.
📚 Consulta: sistema de tipos — https://dart.dev/language/type-system e comprobación de tipos — https://dart.dev/language/operators#type-test-operators.
🌱 Xeradores
Un xerador produce unha secuencia: sync* devolve un Iterable e async* devolve un Stream. yield entrega un elemento; yield* entrega os elementos doutra secuencia.
📚 Xeradores — https://dart.dev/language/functions#generators.
🔄 Outras formas de usar Future e Stream
then() recibe o resultado dun Future, catchError() trata o erro e whenComplete() permite facer unha acción cando remata. Son alternativas ás formas con await e try/catch/finally, con detalles propios no tratamento de erros.
Stream.listen() rexistra callbacks para recibir datos e devolve unha subscrición. Se deixamos de necesitala, podemos cancelala con cancel().
📚 Future — https://api.dart.dev/dart-async/Future-class.html e StreamSubscription — https://api.dart.dev/dart-async/StreamSubscription-class.html.
⚙️ Isolates e bucle de eventos
O bucle de eventos atende tarefas e eventos pendentes. Un isolate ten a súa propia memoria e pode executar traballo separado doutro isolate. Úsase, por exemplo, para cálculos custosos; a comunicación pode facerse con mensaxes a través de portos.
Non necesitamos crear isolates para unha espera de rede con await.
📚 Concorrencia e isolates — https://dart.dev/language/concurrency.
🧰 Máis operacións con coleccións
Ademais das operacións xa vistas, un Set permite facer unións e interseccións. Convén consultar estas opcións cando as necesitemos, en vez de memorizar todos os métodos.
📚 List — https://api.dart.dev/dart-core/List-class.html, Map — https://api.dart.dev/dart-core/Map-class.html e Set — https://api.dart.dev/dart-core/Set-class.html.
➕ Outros operadores e instrucións
- Bits:
&,|,^e os desprazamentos operan sobre a representación binaria dos enteiros. - Cascadas (
..): permiten facer varias operacións sobre o mesmo obxecto sen repetir a variable. - Etiquetas: permiten indicar a que bucle se refire un
breakoucontinueen bucles aniñados. assert: comproba unha condición durante o desenvolvemento cando as asercións están activadas. Non substitúe a validación da entrada: pode estar desactivado.rethrow: dentro duncatch, volve propagar a excepción que se recibiu.
📚 Operadores e precedencia — https://dart.dev/language/operators, bucles — https://dart.dev/language/loops e excepcións e assert — https://dart.dev/language/error-handling.
🕓 Inicialización aprazada e valores ignorados
Un inicializador con late, como late final dato = calcularDato();, avalíase cando se le a variable por primeira vez. É diferente de declarar unha variable e asignala máis tarde.
_ pode indicar que non imos usar un parámetro ou unha variable local. Non é o mesmo que un nome como _dato, relacionado coa privacidade que veremos no Tema 2.2.
📚 late — https://dart.dev/language/variables#late-variables e variables comodín — https://dart.dev/language/variables#wildcard-variables.
🔣 Unicode e paquetes
Un carácter visible, como un emoji, pode ocupar varias unidades de texto. Por iso String.length non sempre coincide coa cantidade de caracteres que vemos. O paquete characters permite traballar con esas unidades visibles, chamadas grafemas.
Nun proxecto Dart podemos engadilo con dart pub add characters. As dependencias quedan recollidas en pubspec.yaml e impórtanse cunha ruta package:.
📚 Texto e caracteres — https://dart.dev/language/built-in-types#characters, paquete characters — https://pub.dev/packages/characters e dependencias — https://dart.dev/tools/pub/dependencies.
📚 Importacións e anotacións
Unha importación pode usar as para asignar un prefixo, show para importar só certos nomes ou hide para excluílos.
As anotacións achegan información ao código. Por exemplo, @override indica que sobrescribimos un membro herdado; veremos isto no Tema 2.2. Tamén se poden crear anotacións propias.
📚 Bibliotecas e importacións — https://dart.dev/language/libraries e anotacións — https://dart.dev/language/metadata.
🖥️ Argumentos de main
main pode recibir unha List<String> cos argumentos escritos ao lanzar o programa. Eses argumentos son distintos das liñas que lemos despois con stdin.
📚 A función main — https://dart.dev/language/functions#the-main-function.