Capitolo 2

Variabili, costanti e i tipi di dato

Un programma deve ricordare dei dati: il prezzo di un prodotto, il punteggio di un gioco, il nome dell'utente. Per farlo usa le variabili (che cambiano) e le costanti (che restano uguali). Imparerai anche i tipi di dato e come inserire i valori dentro al testo.

In questo capitolo impari

Ripasso lampo: quello che serve prima di partire

Rispondi a memoria, poi controlla con il capitolo 1 se sbagli.

Che cosa stampa questo programma?

fun main() {
    println("A")
    print("B")
    println("C")
}
A, B, C su tre righeNo: print("B") non va a capo, quindi C finisce sulla stessa riga.
A poi BCEsatto: println("A") va a capo, print("B") resta sulla riga, println("C") chiude la riga.
ABC tutto su una rigaIl primo comando è println, quindi dopo la A c'è un ritorno a capo.

Il comando dice dove finisce la riga: println va a capo dopo aver stampato, print no. La differenza si vede solo nell'output, mai nel codice.

Quale riga fa apparire un errore?

println("Ciao mondo!")Questa è corretta: il testo è fra virgolette doppie.
println('Ciao mondo!')Esatto: l'apice singolo serve per un solo carattere (Char). Per il testo servono le virgolette doppie.
// println("Ciao mondo!")Questa non dà errore: è un commento, quindi il computer la ignora.

Le virgolette doppie delimitano il testo ("ciao"), l'apice singolo delimita un solo carattere ('c'), che è il tipo Char: per il computer sono due cose diverse.

2.1 var: variabili che cambiano

Una variabile si crea con var, poi si scrive il nome e con = il valore iniziale. Da quel momento il nome è come una scatola con dentro il valore: puoi cambiarlo scrivendo di nuovo nome = nuovoValore.

Le scritture punti += 5 e punti++ sono abbreviazioni comodissime: la prima aggiunge 5, la seconda aumenta di 1.

  1. accessi++ due volte porta la variabile da 0 a 2.
  2. totale += 50 porta 100 a 150; poi totale -= 30 lo porta a 120.
  3. Le due forme compatte fanno esattamente quello che scriveresti per esteso: totale = totale + 50 e poi totale = totale - 30.

2.2 val: costanti che non cambiano

Quando un valore non deve cambiare durante il programma si usa val. Se più avanti provi a modificarlo, Kotlin ti avvisa con un errore: è una cosa voluta, perché protegge il programma dagli errori.

Esegui e osserva il pannello Variabili

Sotto la console vedi la tabella delle variabili: val nome e val annoNascita con il loro tipo e valore. Prova a togliere il commento da nome = "Marco": appare l'errore "è una costante (val)".

var o val? Regola pratica

Parti sempre da val. Passa a var solo quando il valore deve davvero cambiare (contatori, somme accumulate, punteggi). Un programma con pochi var è più facile da capire.

2.3 I tipi di dato

Ogni valore ha un tipo: dice che cosa è quel valore e che cosa ci si può fare. Non è una formalità da imparare a memoria, è quello che decide come si comporta il programma. Guarda questi due programmi: scrivono quasi la stessa cosa, ma il risultato è diverso.

3 è un numero e si somma; "3", con le virgolette, è testo e i testi si incollano l'uno all'altro. Le virgolette doppie cambiano tutto: è il tipo che decide.

Il tipo lo decide il valore, e si riconosce dalla sua forma: senza virgolette è un numero, fra virgolette doppie è testo, fra apici singoli è un solo carattere, true e false sono un sì-o-no. Kotlin guarda la forma e capisce da solo di che tipo si tratta: si chiama inferenza, ed è per questo che da §2.1 scrivi val quantita = 3 senza dichiarare niente. I tipi che useremo sono cinque, e il pannello delle variabili ti mostra quello che Kotlin ha dedotto.

TipoCosa contieneEsempi
Intnumeri interi5, -12, 0
Doublenumeri con la virgola (in Kotlin il punto)3.5, -0.25
Stringtesto fra virgolette doppie"ciao", "5C"
Booleansolo due valori: vero o falsotrue, false
Charun singolo carattere, fra apici singoli'a', '5'

2.4 Dichiarare il tipo con i due punti

Il tipo puoi anche scriverlo tu, con i due punti dopo il nome, come in val media: Double = 7.5. Non è obbligatorio, perché Kotlin lo deduce dal valore: serve in due casi.

Con media il 7 resta intero e la divisione butta via i decimali; con mediaEsatta il 7 diventa 7.0 e la divisione tiene i decimali. Un numero intero entra in un Double senza problemi: anche val prezzo: Double = 5 stampa 5.0. È il contrario che non funziona — scrivere val quantita: Int = 3.5 è un errore, perché 3.5 non entra in un intero.

2.5 Il tipo non cambia più

C'è una cosa che sorprende: una volta deciso, il tipo non cambia più. var ti lascia cambiare il valore, non il tipo. var quantita = 3 potrà valere 5, 10, 100 — sempre un numero intero. Se provi a metterci del testo, il programma si ferma e te lo dice.

L'avviso arriva subito, sulla riga che hai scritto, e nomina i due tipi in gioco: «è dichiarata di tipo Int ma stai assegnando un valore di tipo String». È il tipo che ti protegge: se il controllo non ci fosse, quantita = "tre" passerebbe e il programma darebbe risultati strani molto più tardi, in un punto da cui non capiresti più da dove viene il guaio.

Il tipo e var/val sono due domande diverse

var o val risponde a «il valore può cambiare?». Il tipo risponde a «che cosa contiene?». Le due cose sono indipendenti: var punti = 0 è un Int che può cambiare valore, val punti = 0 è un Int che non può cambiarlo — ma in entrambi i casi resta un numero intero, e in nessuno dei due potrà contenere del testo.

Int e Double non si mescolano da soli

5 / 2 fa 2, perché sono due numeri interi e la parte decimale viene persa. Per ottenere 2.5 serve almeno un numero con la virgola: 5.0 / 2 oppure 5 / 2.0.

  1. 7 / 2 è una divisione fra Int: il risultato è 3, la parte decimale viene tagliata (non arrotondata).
  2. 7.0 / 2 ha un Double, quindi il risultato è decimale: 3.5.
  3. 7 % 2 dà il resto: 1.
  4. L'ultima riga non fa conti: "7" è testo, quindi + attacca i due valori e ottieni 72. Se ti aspettavi 9, serviva "7".toInt() + 2.

2.6 I template di stringa: mettere i valori nel testo

Invece di unire i pezzi con +, puoi scrivere il nome della variabile dentro alla stringa usando il simbolo $. Si chiama template di stringa. Per espressioni più complesse si usano le graffe: ${espressione}.

  1. Dentro ${...} ci sta una vera espressione: Kotlin calcola 3 * 6.5 e poi inserisce il risultato nel testo.
  2. Il risultato è 19.5, un Double: nella console i decimali si vedono con il punto, non con la virgola.
  3. La seconda espressione riusa gli stessi valori: 19.5 - 5 = 14.5.
Quando servono le graffe

"$nome" funziona, ma "$nomeciao" fa cercare una variabile chiamata nomeciao (che non esiste). In casi come questi si scrive "${nome}ciao". Per stampare un dollaro letterale si usa \$.

2.7 Le operazioni

Le operazioni si scrivono come in matematica: + somma, - sottrae, * moltiplica, / divide, % dà il resto. Le parentesi decidono l'ordine, come a scuola.

In quale tipo di dato metti il prezzo 3.5?

IntNo: Int contiene solo numeri interi, senza virgola.
DoubleEsatto: Double è il tipo dei numeri con la virgola.
StringNo: String è testo fra virgolette. "3.5" è una stringa, 3.5 è un numero.

Attenzione a non confondere 3.5 (numero, Double) con "3.5" (testo, String): con il primo si fanno i conti, con il secondo no.

2.8 Cambiare tipo a un valore (conversioni)

Un testo come "42" è una String, non un numero: per fare conti serve convertirlo. Le conversioni più usate sono toInt(), toDouble() e toString() (quest'ultima trasforma un numero in testo).

Che cosa stampa questo programma?

fun main() {
    println("42" + 8)
}
50No: "42" è testo, quindi + non somma, attacca.
428Esatto: il testo "42" e il numero 8 vengono uniti in un'unica stringa.
Un errore, perché non si possono sommare testo e numeroKotlin non dà errore: trasforma il numero in testo e unisce i due pezzi.

Per sommare davvero serve convertire: "42".toInt() + 850.

Il caso più frequente con le conversioni

Sommare un numero intero a un Double va bene (1 + 2.5 fa 3.5), ma sommare due Int e sperare in un decimale non funziona: converti prima uno dei due con .toDouble().

2.9 Riepilogo

ScriviSignificato
var punti = 0variabile intera che può cambiare
val nome = "Anna"costante di testo, non si modifica più
val prezzo: Double = 3.5costante con tipo dichiarato
val media = 7 / val media: Double = 7senza tipo è un Int; dichiarandolo Double vale 7.0
var x = 3 poi x = "tre"errore: il tipo è deciso dalla prima assegnazione e non cambia più
punti += 5, punti++aumenta il valore della variabile
"Ciao $nome"template: inserisce il valore nella stringa
"${a * b}"template con espressione
"5".toInt(), 5.toString()conversioni fra testo e numeri

2.10 Esercizi guidati

Un negozio vende quaderni a 2.50 euro e penne a 1.20 euro. Usando delle costanti val per i prezzi e delle variabili var per le quantità, calcola e stampa: il totale dei quaderni, il totale delle penne e il totale generale.

Il totale dei quaderni è quantitaQuaderni * prezzoQuaderno. Crea delle val per i due subtotali e poi sommale per il totale generale.

  1. I prezzi non cambiano durante il programma, quindi sono val: così non si possono modificare per sbaglio.
  2. Le quantità potrebbero cambiare (magari l'utente le legge da input nel capitolo 3), quindi sono var.
  3. quantitaQuaderni * prezzoQuaderno moltiplica un Int per un Double: il risultato è un Double, perché basta un numero con la virgola per rendere decimale il risultato.
  4. Nel template "Quaderni: $totaleQuaderni euro" le graffe non servono: dopo il dollaro c'è il nome della variabile e poi uno spazio.

Dato un numero di secondi (per esempio 3725), calcola quante ore, quanti minuti e quanti secondi rappresentano. Usa la divisione intera e l'operatore resto %.

Un'ora ha 3600 secondi, un minuto 60. Le ore si ottengono con secondiTotali / 3600, poi quello che avanza si lavora con % 3600.

  1. secondiTotali / 3600 è una divisione fra interi: 3725 / 3600 fa 1, la parte decimale viene tagliata via.
  2. % 3600 restituisce il resto, cioè i secondi che non formano un'ora intera: 3725 % 3600 = 125.
  3. Con quei 125 secondi si ripete lo stesso ragionamento con i minuti: 125 / 60 = 2 minuti e 125 % 60 = 5 secondi.
  4. Questo schema (dividere e poi usare il resto) si usa ogni volta che serve scomporre una quantità in unità più piccole: euro e centesimi, metri e centimetri, ore e minuti.

Crea le variabili di un personaggio di un videogioco: nome (String), livello (Int), punti vita (Int), velocità (Double) e se ha la spada (Boolean). Poi: aumenta il livello di 1, togli 15 punti vita, raddoppia la velocità e stampa una scheda finale con tutti i valori in ordine, usando i template di stringa.

Per aumentare il livello scrivi livello++. Per togliere punti vita: puntiVita -= 15. Per raddoppiare la velocità: velocita *= 2.

  1. livello++ aumenta di uno: passa da 4 a 5.
  2. puntiVita -= 15 è la forma compatta di puntiVita = puntiVita - 15.
  3. velocita *= 2 funziona anche con i Double: 3.5 diventa 7.0 (nella console il numero decimale si vede con il punto).
  4. haLaSpada resta true perché è una val: il personaggio può perdere punti vita, ma non la spada.

Questo programma deve stampare il totale di 3 quaderni e il prezzo con lo sconto del 10%, ma non funziona. Eseguilo, leggi il messaggio di errore e correggi un errore alla volta: alla fine deve stampare due righe, Totale: 7.5 euro e Scontato: 6.75 euro.

Tre cose non vanno: manca la parola val o var davanti a totale; i decimali si scrivono con il punto, non con la virgola; il nome di una variabile va scritto sempre uguale (controlla scontato/scontado).

  1. 0,9 con la virgola: Kotlin vuole il punto per i decimali. È l'errore che vedi per primo, perché la punteggiatura viene controllata prima di eseguire.
  2. totale = prezzo * quantita senza val o var: Kotlin non sa che stai creando una variabile nuova, quindi non la trova.
  3. prezzo = 2.00: prezzo è una val e non si può riassegnare. Nel programma corretto la riga non serve.
  4. scontado non esiste: il nome dichiarato è scontato, e Kotlin distingue ogni lettera.
  5. Il risultato finale sono due righe: Totale: 7.5 euro e Scontato: 6.75 euro.
  • so scegliere fra var e val e so spiegare perché
  • so usare +=, -= e ++
  • so riconoscere i tipi Int, Double, String, Boolean, Char, e so che cosa li distingue dalla forma del valore
  • so spiegare perché una variabile non può cambiare tipo, e che cosa serve dichiararlo con i due punti
  • so prevedere quando una divisione dà un risultato intero e quando decimale
  • so inserire un valore dentro una stringa con $nome e ${espressione}
  • so usare % per ottenere il resto e so convertire con toInt(), toDouble(), toString()
  • so leggere un messaggio di errore e correggere il programma da solo