Basi del linguaggio Dart

Variabili

Dart è un linguaggio tipizzato quindi tutte le variabili devono essere inizializzate con un tipo specifico al momento della loro inizializzazione. Questo tipo può essere esplicito

int aNumber = 42;
print(aNumber.runtimeType); /* int */

o implicito

var aNumber = 42;
print(aNumber.runtimeType); /* int */

Tipo Null

È possibile usare var senza inizializzazione, il tipo associato è Null che in Dart è un tipo (non un valore come, ad esempio in Java) che ha un solo possibile valore: null.

var aVariable;
print(aVariable); /* null */
print(aVariable.runtimeType); /* Null */
Attenzione

In Dart bisogna fare attenzione alla differenza tra Null (N maiuscola) che si riferisce al tipo e a null (n minuscola) che si riferisce al valore.

Inizializzazione

Dart non permette l’uso di variabili non-nullable che non siano inizializzate, le variabili nullable non sono esplicitamente inizializzate viene assegnato null.

int aVar;
print(aVar); /* Errore */
int? bVar;
print(bVar); /* Ok, output is 'null' */
int cVar;
cVar = 10;
print(cVar); /* Ok, assegnamento prima dell'uso */

In certi casi può accadere che l’inizializzazione avvenga, ma che il compilatore non se ne “accorga” e che insista con un errore di inizializzazione. Per aggirare questo problema, si può usare la parola chiave late prima della dichiarazione che comunica al compilatore che la variabile verrà inizializzata prima di essere utilizzata.

late int aVar;
/* some code with assignment to aVar */
print(aVar); /* Ok unless the compiler is sure aVar is not assigned */

Null safety

Dart scoraggia l’utilizzo del tipo Null attraverso un meccanismo di null safety. I tipo in Dart sono tutti oggetti (a differenza, ad esempio, di Java dove ci sono oggetti e tipi fondamentali), ma se non esplicitamente dichiarati nullable le variabili non possono avere il valore null.

int nonNullableVar = null; /* Error, non-nullable variable*/
int? nullableVar = null; /* Ok, nullable variable */

Nell’esempio sopra nonNullableVar è un intero che non può avere il valore null mentre nullableVar dichiarato int? (attenzione al ?) può assumere il valore null.

Ovviamente, la null safety vale per ogni tipo presente in Dart: ad esempio int, double e String sono null-safe, mentre int?, double? e String? sono le corrispondenti versione non null-safe.

Esercizio

Creare variabili di tipo int, double e String, sia nullable sia non-nullable; considerando due variabili a e b di tipo diverso, entrambe nullable e con valore null, cosa produce la seguente istruzione?

print(a == b); /* ??? */

Tipi di variabili built-in

In Dart ci sono diversi tipi già definiti (detti built-in) i più importanti sono i seguenti:

  • numeri: int e double;
  • stringhe: String
  • booleani: bool
  • contenitori: List, Set e Map
  • classe base: Object
  • tipo nullo: Null
  • programmazione asincrona: Future, Stream
  • altri: Runes, Symbols, Enum, Iterable, Never

Per maggiori informazione si può riferimento alla guida introduttiva a Dart

Funzioni

La sintassi Dart per le funzioni è simile a quella di altri linguaggi tipo C e Python (Java ha solo il concetto di metodo e non quello di funzione che non sia metodo).

double sum(double a, double b) {
  return a + b;
}
Attenzione

Dart è un linguaggio ad oggetti ed anche le funzioni sono oggetti, in particolare il loro tipo è Function. Questo fatto ha implicazioni:

  • le funzioni possono essere assegnate a variabili;
  • le funzioni possono essere argomenti di altre funzioni;
  • due funzioni possono essere confrontate.

Parametri

In Dart è possibile passare parametri posizionali (positional) o parametri nominali (named). La sintassi per i parametri posizionali è quella usuale, mentre i parametri nominali si racchiudono in parentesi graffe. Di norma i parametri nominali sono facoltativi, ma possono essere resi obbligatori con la parola chiave required.

// positional + named arguments
double logF(double x, {double base = e}) {
  return log(x)/log(base);
}
// required named
double foo({required double x}) {
  return x;
}

Per indicare i parametri nominali la sintassi prevede l’utilizzo di {nome: attuale} ad indicare che al parametro con nome nome andrà assegnato il valore della variabile attuale.

print(logF(4, base: 2));
print(foo(x: 1.11));

Arrow functions

Quando l’unica istruzione di una funzione è una singola espressione, si può utilizzare la notazione arrow function per cui

double product(double a, double b) {
  return a * b;
}

può essere compattamente scritta come

double product(a, b) => a*b;
  • Michele Schimd © 2024
  • Ultimo aggiornamento: 17/02/2024
  • Materiale di studio e di esercizio per gli alunni dello Zuccante.

Creative Commons License