Condizioni: far scegliere al programma
Fino ad ora i programmi eseguivano tutte le istruzioni in ordine. Adesso impari a
decidere: eseguire un pezzo di codice solo se una condizione è vera.
Si impara in due modi: if (se) e when (quando).
- a eseguire un pezzo di codice solo se una condizione è vera:
if/else/else if; - a confrontare valori (
>,<,==…) e a unire due condizioni (&&,||); - a scegliere fra più strade con
when. - In fondo vedi anche come un
ifpuò dare un valore da mettere in una variabile.
Ripasso lampo: leggere i dati e convertirli
Prima di decidere, il programma deve avere i dati: ripasso del
capitolo 3. Negli esempi di questo capitolo le letture usano
readlnOrNull()?.toIntOrNull() ?: 0: se il dato manca o non è un numero,
la condizione riceve comunque 0.
L'utente scrive 12. Che cosa stampa questo programma?
fun main() {
val n = readln()
println(n + 1)
}13No: n è testo, quindi n + 1 attacca i due pezzi invece di sommarli.121Esatto: manca toInt(). Con readln().toInt() il risultato sarebbe 13.readln() restituisce sempre testo: senza .toInt() il + unisce invece di sommare. È l'errore più frequente di tutto il manuale.
L'utente scrive ciao. Che cosa stampa questo programma?
fun main() {
val n = readln().toIntOrNull() ?: 0
println(n * 2)
}0Esatto: toIntOrNull() dà null, e ?: mette 0 al suo posto. 0 * 2 è 0.toInt(); con toIntOrNull() il programma continua.ciaociaoNo: ?: scarta il testo non convertibile e usa il valore di riserva.toIntOrNull() non fa mai fermare il programma: quando la conversione non riesce restituisce null, e il valore di riserva lo scegli tu con ?:.
4.1 if: eseguire solo se...
La forma base è if (condizione) { ... }: le istruzioni fra graffe vengono eseguite
solo se la condizione è vera. Con else si indica che cosa fare quando è falsa.
Se il ramo contiene una sola istruzione puoi scrivere if (eta >= 18) println("Maggiorenne").
Per cominciare usa sempre le graffe: il codice resta chiaro e non fai errori quando aggiungi istruzioni.
4.2 Confronti e operatori logici
Una condizione è un'espressione che vale true o false.
Si costruisce con gli operatori di confronto e si combina con quelli logici.
| Operatore | Significato | Esempio |
|---|---|---|
== | uguale a (due segni di uguale!) | voto == 10 |
!= | diverso da | nome != "Anna" |
> >= | maggiore, maggiore o uguale | eta >= 18 |
< <= | minore, minore o uguale | prezzo < 10 |
&& | e: vero solo se lo sono entrambe | eta >= 14 && eta < 18 |
|| | o: vera se lo è almeno una | giorno == "sab" || giorno == "dom" |
! | non: rovescia vero e falso | !haLaSpada |
Che cosa stampa questo programma?
fun main() {
val eta = 16
if (eta >= 14 && eta < 18) println("motorino")
else println("no")
}noNo: 16 >= 14 è vera e 16 < 18 è vera, quindi si entra nel primo ramo.motorinoEsatto: con && servono entrambe vere. Qui lo sono.else, e comunque la prima condizione è già vera.&& è vero solo se lo sono tutte e due. Basta una falsa e si va nell'else.
if (eta = 18) è un errore: con = si assegna un valore.
Per confrontare si usa sempre ==.
4.3 else if: più di due possibilità
Quando le possibilità sono più di due si usano uno o più else if, ma si
chiude sempre con else. Kotlin le controlla dall'alto verso il basso e si
ferma alla prima condizione vera.
Nel prossimo riquadro c'è anche un if che non stampa:
mette un testo in una variabile. Lo spieghiamo nella sezione dopo.
Per ora concentra sull'else if: quale ramo parte con voto = 7?
- Con
voto = 7la prima condizione (7 >= 9) è falsa, la seconda (7 >= 6) è vera: Kotlin stampaPromossoe non guarda le condizioni successive. - Il secondo
ifnon stampa niente: restituisce il testo"promosso/a", che finisce nella variabileesito. È l'ifche dà un valore, spiegato nella sezione 4.4. - Da qui le due righe di output:
PromossoeEsito: promosso/a.
Con voto = 9 la prima condizione è vera e il programma non guarda le altre.
Se avessi messo per prima voto >= 6, anche un 10 sarebbe finito in "Sufficiente":
si va sempre dal caso più restrittivo a quello più generico.
Che cosa stampa questo programma?
fun main() {
val voto = 9
if (voto >= 6) println("sufficiente")
else if (voto >= 9) println("ottimo")
else println("insufficiente")
}ottimoIl voto 9 soddisfa anche 9 >= 6, e quella condizione viene controllata prima.sufficienteEsatto: Kotlin si ferma alla prima condizione vera, quindi il ramo >= 9 non viene mai raggiunto con questo ordine.insufficienteNo: la prima condizione è vera, quindi si entra in quel ramo.Le condizioni vanno scritte dalla più stretta alla più larga. Qui l'ordine giusto è >= 9 prima e >= 6 dopo.
4.4 if come espressione: assegnare un valore
In Kotlin if può restituire un valore: è il modo più compatto
per scegliere fra due valori e metterli in una variabile.
4.5 when: tanti casi in modo ordinato
when confronta un valore con tanti casi. È come una catena di else if,
ma molto più leggibile. Il caso else è obbligatorio quando nessuna condizione
copre tutti i valori possibili.
in 0..59
in 0..59 si legge "da 0 a 59, estremi compresi".
Il when sceglie quel ramo se il voto è dentro quell'intervallo.
Con il voto 78: 0–59 no, 60–100 sì → stampa Sufficiente.
Gli intervalli 1..10 li userai anche nei cicli, nel
capitolo 5. L'idea è la stessa: un tratto di numeri.
6non è nella prima riga di casi, ma è nella seconda:Weekend.15 > 10è vero e15 % 5 == 0è vero: con&&servono entrambe vere, quinditrue.15 > 20è falso e15 < 0è falso: con||basta una condizione vera, quindifalse.
Che cosa stampa questo programma?
fun main() {
val n = 15
when {
n % 15 == 0 -> println("3 e 5")
n % 3 == 0 -> println("solo 3")
else -> println("altro")
}
}solo 315 è divisibile anche per 3, ma quella riga sta dopo. Kotlin si ferma alla prima vera.3 e 5Esatto: 15 % 15 == 0 è la prima condizione vera.altroNo: la prima condizione è vera, l'else non si raggiunge.Anche nel when vale l'ordine: si prende il primo caso vero e gli altri non si guardano.
val premio = when (punti) { ... else -> 0 } funziona come if:
il valore del ramo scelto diventa il valore di tutta l'espressione.
1. Il when esegue istruzioni (esempi 9–11).
Se nessun caso coincide, non succede niente. Nessun errore.
2. Il when dà un valore
(val premio = when (punti) { ... }).
Allora l'else è obbligatorio: Kotlin deve sapere che cosa mettere
nella variabile in ogni caso.
Nel laboratorio qui sotto l'else c'è già e il programma funziona.
Prova tu: commenta la riga else -> "niente", esegui, leggi l'errore.
Poi togli il commento e riesegui: deve stampare Premio: niente.
Abitudine: metti sempre l'else.
4.6 Riepilogo
| Scrivi | Significato |
|---|---|
if (c) { ... } else { ... } | due strade possibili |
if (c) { ... } else if (c2) { ... } else { ... } | più strade, in ordine |
val x = if (c) a else b | una variabile che prende uno dei due valori |
when (x) { 1 -> ...; else -> ... } | confronto con tanti casi |
when { c1 -> ...; c2 -> ...; else -> ... } | catena di condizioni |
4.7 Esercizi guidati
Leggi un voto da 0 a 10. Attenzione: le fasce non sono quelle dell'esempio 5.
Qui usi questa scala, da 0 a 10:
10 → Eccellente; 8 o 9 → Buono;
6 o 7 → Sufficiente; sotto 6 → Insufficiente.
Usa if / else if / else. Parti dal caso più alto.
Stampa una sola parola: con il voto 5 deve uscire Insufficiente.
Parti dal caso più alto o dal più basso e prosegui in ordine:
if (voto >= 10) ... else if (voto >= 8) ....
- Le condizioni vanno dal caso più alto al più basso. Con voto = 10 la prima condizione è vera e le altre non vengono nemmeno guardate.
- Se l'input non è un numero,
?: -1assegna -1 e il programma finisce nel ramoelseinvece di fermarsi con un errore. - Ogni ramo ha un solo
println: avresti potuto omettere le graffe, ma così il codice è pronto per aggiungere altre istruzioni.
Leggi un anno e stabilisci se è bisestile. Regola: un anno è bisestile se è divisibile per 4,
tranne gli anni divisibili per 100, che sono bisestili solo se divisibili per 400.
Prova con 1900 (non bisestile), 2000 (bisestile) e 2024 (bisestile).
Con 1900 stampa esattamente 1900 non è un anno bisestile.
Puoi scrivere tutte le condizioni in un unico if con && e
||: anno % 4 == 0 && (anno % 100 != 0 || anno % 400 == 0).
anno % 4 == 0è la condizione principale: senza quella nessun anno può essere bisestile.- Le parentesi attorno a
(anno % 100 != 0 || anno % 400 == 0)sono essenziali:&&ha la precedenza su||, quindi senza parentesi il significato cambierebbe. - 1900 è divisibile per 4 e per 100 ma non per 400 → non bisestile. 2000 è divisibile per 400 → bisestile. 2024 non è divisibile per 100 → bisestile.
- Il risultato viene messo in una
valcon un nome chiaro: il codice che segue si legge come una frase in italiano.
Il distributore automatico ha questo menu: 1 = acqua (0.50), 2 = succo (1.20), 3 = caffè (0.90),
4 = snack (1.50). Leggi il numero scelto e i soldi inseriti, poi stampa cosa è stato scelto
(Hai scelto: ...) e una seconda riga: il resto, oppure
Soldi insufficienti: mancano ... euro.
Se il numero non è nel menu: Hai scelto: Scelta non valida e
Nessun prodotto erogato.
Con scelta 3 e 1.50 euro: Hai scelto: Caffè e
Resto: 0.6 euro.
Con when assegna il prezzo: val prezzo = when (scelta) { 1 -> 0.50 ... else -> 0.0 }.
Il resto è soldi - prezzo: se il prezzo è 0.0 non c'è nulla da comprare.
- Un
whencome espressione restituisce il valore del ramo scelto: il primo lo usiamo per il nome, il secondo per il prezzo. - L'
elsedelwhenserve sia per il nome sia per il prezzo: se la scelta non è 1-4 il prezzo resta 0.0. - Dopo il
whenci sono tre casi distinti gestiti conif / else if / else: prezzo nullo, soldi sufficienti, soldi insufficienti. soldi >= prezzoconfronta dueDouble: il confronto funziona anche con i decimali.
Questo programma parte senza errori, ma con voto = 9 stampa
Sufficiente invece di Ottimo. Eseguilo, confronta l'output con quello
atteso e correggi solo l'ordine delle condizioni, senza cambiare i testi stampati.
Kotlin si ferma alla prima condizione vera: il caso più stretto
(voto >= 9) deve stare prima di quello più largo (voto >= 6).
- Il codice di partenza compila: l'errore è logico, non di sintassi. Con
voto = 9la prima condizione9 >= 6è già vera. - Kotlin entra nel primo ramo e non guarda gli altri: il ramo
>= 9diventa irraggiungibile. - Mettendo
voto >= 9per primo, il 9 finisce in "Ottimo", il 7 in "Sufficiente" e il 4 in "Insufficiente". - Regola generale: le condizioni vanno scritte dalla più stretta alla più larga.
Il programma deve dire se un voto è sufficiente, ma non funziona. Con 7 deve stampare due righe: Sufficiente e Voto valido. Con 5 deve stampare solo Insufficiente.
Per confrontare serve == (due uguali); le due condizioni di un && stanno dentro le stesse parentesi tonde dell'if.
if (voto = 6)usa un solo=, che assegna: per confrontare si scrivevoto >= 6ovoto == 6.- Le graffe non sono obbligatorie con una sola istruzione, ma con
ifeelsesu più righe evitano di sbagliare a quale ramo appartiene l'istruzione. if (voto >= 6) && (voto <= 10)chiude le parentesi troppo presto: la condizione completa va dentro una sola coppia di parentesi,if (voto >= 6 && voto <= 10).- Kotlin controlla tutta la condizione e solo dopo decide: un
&&fuori posto non è "quasi giusto", è un errore.
if, else if e else>, <, >=, <=, ==, !=&&, || e !if come espressione per assegnare un valorewhen con valori, intervalli e casi else