Condizionale, blocchi - Unicam · Condizionale, blocchi Comando Condizionale Blocchi Gestione dei...

Post on 20-Jul-2020

28 views 0 download

Transcript of Condizionale, blocchi - Unicam · Condizionale, blocchi Comando Condizionale Blocchi Gestione dei...

1Laboratorio di Programmazione - Luca Tesei

Condizionale, blocchi

Comando Condizionale

Blocchi

Gestione dei blocchi da parte della macchina astratta Java

Visibilità (scope) ed esistenza delle variabili di frame nei blocchi

2Laboratorio di Programmazione - Luca Tesei

Scelte

● Fino ad ora il corpo dei metodi che abbiamo scritto aveva solo un modo di essere eseguito: in sequenza dalla prima istruzione all’ultima

● In applicazioni non banali il comportamento dei metodi deve variare a seconda dei dati di input

● Il programma deve prendere delle decisioni in base ai dati in suo possesso

● Vediamo quindi come si fa ad effettuare delle scelte nei programmi

3Laboratorio di Programmazione - Luca Tesei

Il costrutto if

● Riconsideriamo la classe BankAccount● Il metodo withdraw preleva dal conto una cifra

qualsiasi● In una applicazione reale, invece, il metodo

dovrebbe controllare se la cifra richiesta è disponibile e solo in quel caso effettuare il prelievo

● Per far questo si può usare lo statement (enunciato) if

4Laboratorio di Programmazione - Luca Tesei

Il costrutto if

public class BankAccount {...public void withdraw(double amount) { if (amount <= balance) balance = balance – amount; }...}

5Laboratorio di Programmazione - Luca Tesei

Il costrutto if

● In questo modo l’assegnamento balance = balance – amount; viene eseguito solo se la condizione tra parentesi tonde è vera.

● Il significato di (amount <= balance) è un valore di tipo boolean, cioè un valore nell’insieme {true, false}

● L’espressione è vera (true) se il valore della variabile amount (parametro esplicito del metodo) è minore o uguale al valore della variabile istanza balance dell’oggetto si cui si sta eseguendo il metodo

6Laboratorio di Programmazione - Luca Tesei

Rappresentazione con diagramma a blocchi

amount <= balance

balance = balance - amount

Vero

Falso

7Laboratorio di Programmazione - Luca Tesei

Il costrutto if

● Se la condizione risulta falsa l’if da solo non fa niente e il controllo passa al comando successivo

● Potremmo pensare, comunque, di avvertire in qualche modo l’utente che il prelievo non è possibile

● Per far questo è possibile aggiungere all’if un’alternativa (else) che contiene un comando che viene eseguito solo se la condizione è falsa (false)

8Laboratorio di Programmazione - Luca Tesei

Il costrutto if-else

public class BankAccount {...public void withdraw(double amount) { if (amount <= balance) balance = balance – amount; else System.out.println( “Importo Richiesto Non Disponibile”); }...}

Attenzione! Questo tipo di output non è adatto quando laclasse è di Back-end. In una versione corretta invece di

stampare un messaggio va lanciata un'eccezione o restituitoun valore di ritorno che segnala l'anomalia

9Laboratorio di Programmazione - Luca Tesei

Il costrutto if-else

La semantica dell’if-else è la seguente:1)Viene calcolato il valore dell’espressione di tipo boolean fra parentesi tonde

2)Se l’espressione ha valore true allora viene eseguito il comando che si trova tra l’espressione e la parola riservata else.

3)Se l’espressione ha valore false allora viene eseguito il comando che si trova dopo la parola riservata else

4)In ogni caso, dopo l’esecuzione del comando corrispondente (caso 2 o caso 3), l’esecuzione continua con l’enunciato che segue

10Laboratorio di Programmazione - Luca Tesei

Rappresentazione con diagramma a blocchi

amount <= balance

balance = balance - amount

Vero

Falso

Importo Richiesto Non Disponibile

11Laboratorio di Programmazione - Luca Tesei

Attenzione: errore!

public class BankAccount {...public void withdraw(double amount) { if (amount <= balance) balance = balance – amount; if (amount > balance) System.out.println( “Importo Richiesto Non Disponibile”); }...}

Errore! Non è la stessa cosa dell'if-else: dopo l'esecuzione delprimo if il valore di balance può essere diverso e l'espressionenegata potrebbe diventare vera, mentre all'inizio era falsa!

12Laboratorio di Programmazione - Luca Tesei

Rappresentazione con diagramma a blocchi

amount <= balance

balance = balance - amount

Vero

Falso

amount > balance

Vero

Falso

Importo Richiesto Non Disponibile

Percorso chenon esiste nell’if-else

13Laboratorio di Programmazione - Luca Tesei

Blocchi

● Il costrutto if o if-else prevede che sia inserito un solo comando dopo l’espressione tra parentesi e dopo la parola riservata else

● Invece potremmo aver bisogno di eseguire più di un comando nel “ramo true” e/o nel “ramo false”

● Per far questo usiamo la possibilità, offerta dal linguaggio Java, di creare blocchi di comandi

14Laboratorio di Programmazione - Luca Tesei

Blocchi

● Un blocco inizia con { e finisce con }● All’interno delle parentesi graffe possono essere

inseriti zero o più enunciati● Un blocco può essere inserito in qualunque

punto all’interno del corpo di un metodo● I blocchi possono essere annidati: un blocco

può contenere altri blocchi che a loro volta possono contenere altri blocchi

● Un blocco viene visto dalla macchina astratta java come un unico enunciato

15Laboratorio di Programmazione - Luca Tesei

Blocchi

● Supponiamo ad esempio che se un utente tenta di prelevare del denaro che non ha, oltre alla stampa del messaggio, venga anche decrementato il saldo di una penale costante

● Possiamo scrivere così:

16Laboratorio di Programmazione - Luca Tesei

Blocchi

public class BankAccount {...public static final double PENALE = 5.0;public void withdraw(double amount) { if (amount <= balance) { double newBalance = balance – amount; balance = newBalance; } else { System.out.println(“Importo Richiesto Non

Disponibile”); balance = balance – PENALE; System.out.println(“Penale di “ + PENALE + “ euro applicata”); } }...}

Blocco del ramotrue

Blocco del ramofalse

17Laboratorio di Programmazione - Luca Tesei

Blocchi e variabili di frame

● Nel blocco del ramo “true” dichiariamo una nuova variabile di tipo double che chiamiamo newBalance

● In Java, quando si apre un nuovo blocco, viene sempre aggiunto un frame nuovo nella pila di frame contenuta nell’attivazione corrente

● Le variabili dichiarate all’interno del nuovo blocco hanno scope (contesto) limitato ad esso

● Esse cesseranno di esistere quando l’esecuzione di tutti i comandi del blocco sarà finita e, quindi, il frame verrà buttato via

18Laboratorio di Programmazione - Luca Tesei

Visibilità delle variabili e blocchi

• Ricordiamoci che quando viene riferita una variabile con un certo nome all’interno di un metodo la macchina astratta Java segue un algoritmo ben preciso per rintracciarla:

1. Cerca il nome all’interno del frame in testa alla pila di frame dell’attivazione corrente

3. Se lo trova allora quella è la variabile riferita4. Se non lo trova lo cerca all’interno dei frame

sottostanti dal più recente a quello più in basso. 5. Se non lo trova in nessun frame la variabile non è

stata dichiarata (è un errore che viene segnalato dal compilatore)

19Laboratorio di Programmazione - Luca Tesei

Visibilità delle variabili e blocchi: conflitto

● Il compilatore non permette, all’interno della stessa attivazione, di ridefinire un nome di variabile, anche se in un blocco interno

● Facciamo un esempio. Supponiamo di trovarci nella seguente situazione alla chiamata del metodo withdraw su un certo oggetto creato in un main

20Laboratorio di Programmazione - Luca Tesei

Visibilità delle variabili e blocchi

public void withdraw(double amount) { double newBalance = balance – amount; if (newBalance >= 0) balance = newBalance; else { System.out.println(“Importo Richiesto Non

Disponibile”); { // Nuovo Blocco // non posso ridichiarare newBalance double penaltyBalance = balance – PENALE; balance = penaltyBalance; } // penaltyBalance non esiste più! System.out.println(“Penale di “ + PENALE + “ euro applicata”); } }

Posizione attuale

21Laboratorio di Programmazione - Luca Tesei

Visibilità delle variabili e blocchi

Attivazione delmain (congelata/non raggiungibile)

this

amount 100.0

BankAccount

balance 90.0

HeapAttivazione dellachiamata di withdraw

Primo frame (corrisponde al blocco principale del metodo)

22Laboratorio di Programmazione - Luca Tesei

Visibilità delle variabili e blocchi

public void withdraw(double amount) { double newBalance = balance – amount; if (newBalance >= 0) balance = newBalance; else { System.out.println(“Importo Richiesto Non Disponibile”); { // Nuovo Blocco // Non posso ridichiarare newBalance double penaltyBalance = balance – PENALE; balance = penaltyBalance; } // penaltyBalance non esiste più! System.out.println(“Penale di “ + PENALE + “ euro applicata”); } }

Posizione attuale

23Laboratorio di Programmazione - Luca Tesei

Visibilità delle variabili e blocchi

Attivazione delmain (congelata/non raggiungibile)

this

amount 100.0

BankAccount

balance 90.0newBalance -10.0

24Laboratorio di Programmazione - Luca Tesei

Visibilità delle variabili e blocchi

public void withdraw(double amount) { double newBalance = balance – amount; if (newBalance >= 0) balance = newBalance; else { System.out.println(“Importo Richiesto Non

Disponibile”); { // Nuovo Blocco // non posso ridichiarare newBalance double penaltyBalance = balance – PENALE; balance = penaltyBalance; } // penaltyBalance non esiste più! System.out.println(“Penale di “ + PENALE + “ euro applicata”); } }

Posizione attuale

25Laboratorio di Programmazione - Luca Tesei

Visibilità delle variabili e blocchi

Attivazione delmain (congelata/non raggiungibile)

this

amount 100.0

BankAccount

balance 90.0newBalance -10.0

L’apertura di un nuovo bloccocorrisponde alla crazione di un nuovo frame in testa allapila

26Laboratorio di Programmazione - Luca Tesei

Visibilità delle variabili e blocchi

public void withdraw(double amount) { double newBalance = balance – amount; if (newBalance >= 0) balance = newBalance; else { System.out.println(“Importo Richiesto Non

Disponibile”); { // Nuovo Blocco // non posso ridichiarare newBalance double penaltyBalance = balance – PENALE; balance = penaltyBalance; } // penaltyBalance non esiste più! System.out.println(“Penale di “ + PENALE + “ euro applicata”); } }

Posizione attuale

27Laboratorio di Programmazione - Luca Tesei

Visibilità delle variabili e blocchi

Attivazione delmain (congelata/non raggiungibile)

BankAccount

balance 90.0

Heap

this

amount 100.0

newBalance -10.0

penaltyBalance 85.0

Nuovo frame per il nuovoblocco. La variabile penaltyBalance nasce e muorecon il nuovo blocco

28Laboratorio di Programmazione - Luca Tesei

Visibilità delle variabili e blocchi

public void withdraw(double amount) { double newBalance = balance – amount; if (newBalance >= 0) balance = newBalance; else { System.out.println(“Importo Richiesto Non

Disponibile”); { // Nuovo Blocco // non posso ridichiarare newBalance double penaltyBalance = balance – PENALE; balance = penaltyBalance; } // penaltyBalance non esiste più! System.out.println(“Penale di “ + PENALE + “ euro applicata”); } }

Posizione attuale

29Laboratorio di Programmazione - Luca Tesei

Visibilità delle variabili e blocchi

Attivazione delmain (congelata/non raggiungibile)

BankAccount

balance 85.0

thisamount 100.0

newBalance -10.0

Il frame per il nuovoblocco e la relativa variabile penaltyBalance vengonobuttati via

30Laboratorio di Programmazione - Luca Tesei

Visibilità delle variabili e blocchi

public void withdraw(double amount) { double newBalance = balance – amount; if (newBalance >= 0) balance = newBalance; else { System.out.println(“Importo Richiesto Non Disponibile”); { // Nuovo Blocco // non posso ridichiarare newBalance double penaltyBalance = balance – PENALE; balance = penaltyBalance; } // penaltyBalance non esiste più! System.out.println(“Penale di “ + PENALE + “ euro applicata”); } } Posizione attuale Blocco del ramo false chiuso

31Laboratorio di Programmazione - Luca Tesei

Visibilità delle variabili e blocchi

Attivazione delmain (congelata/non raggiungibile)

BankAccount

balance 85.0

Heap

thisamount 100.0

newBalance -10.0

Il frame per il bloccodel ramo “false” dell’ifviene buttato via (non contienevariabili) alla fine del blocco

32Laboratorio di Programmazione - Luca Tesei

Visibilità delle variabili e blocchi

● Alla fine dell’esecuzione del blocco principale di withdraw:

public void withdraw(double amount) { double newBalance = balance – amount; ... }

● viene cancellato il frame principale, ma anche tutta l’attivazione creata per eseguirlo

33Laboratorio di Programmazione - Luca Tesei

Visibilità delle variabili e blocchi

Attivazione delmain (di nuovo in

esecuzione)

BankAccount

balance 85.0

Heap

34Laboratorio di Programmazione - Luca Tesei

Esercizio

● Riprogettare e reimplementare la classe BankAccount secondo i seguenti requisiti:

● è possibile chiedere ad un BankAccount se un prelievo è possibile e, se c'è, a quanto ammonta la penale

● il metodo withdraw non stampa sullo standard output, ma segnala ciò che ha fatto tramite un numero intero scelto fra le due seguenti costanti intere (da definire): WITHDRAW_OK, WITHDRAW_FAILED_PENALTY