12/10/16 Principi di Progettazione del Software a.a. 2016-2017 Fondamenti di Java (pt. 2) ing. Roberto Vergallo Obiettivi della lezione ■ Le strutture di controllo – Conoscere le strutture decisionali if e if/else – Conoscere le strutture iterative for e do/while – Comprendere le iterazioni controllate da contatori – Comprendere la selezione multipla usando switch – Imparare a usare le istruzioni di controllo break e continue ■ I messaggi – Riferimenti a oggetti – Passaggio di parametri ■ Package Java – Modificatore public – Istruzione import Fondamenti di java 2 Roberto Vergallo 1 12/10/16 Le strutture di controllo ■ Espressioni ed istruzioni per il controllo di flusso forniscono al programmatore il meccanismo per decidere se e come eseguire blocchi di istruzioni condizionatamente a meccanismo decisionali definiti all’interno della applicazione. 3 Fondamenti di java Roberto Vergallo Le strutture di controllo (cont.) Istruzione if ■ L’istruzione per il controllo di flusso if consente all’applicazione di decidere, in base ad una espressione booleana, se eseguire o no un blocco di codice. Sintassi: Se boolean_expr restituisce il valore true, verrà eseguito il blocco di istruzioni successivo, in caso contrario il controllo passerà alla prima istruzione successiva al blocco if. if (boolean_expr) { istruzione; [istruzione] } if (i < 100) System.out.println ("minore di 100"); Fondamenti di java 4 Roberto Vergallo 2 12/10/16 Le strutture di controllo (cont.) L’istruzione if-else ■ Una istruzione if può essere opzionalmente affiancata da una istruzione else. Questa forma particolare dell’istruzione if consente di decidere quale blocco di codice eseguire tra due blocchi di codice. Sintassi: Se boolean_expr restituisce il valore true verrà eseguito il blocco di Istruzioni di if, altrimenti il controllo verrà passato ad else e verrà eseguito il secondo blocco di istruzioni. if (boolean_expr) { istruzione; [istruzione] } else if (i < 100) System.out.println ("minore di 100"); else System.out.println ("maggiore o uguale a 100"); { istruzione; [istruzione] } 5 Fondamenti di java Roberto Vergallo Le strutture di controllo (cont.) Istruzioni if, if-else annidate ■ Una istruzione if annidata rappresenta una forma particolare di controllo di flusso in cui una istruzione if o if-else è controllata da un’altra istruzione if o if-else. Sintassi: if(espressione) { istruzione if (espressione2) { istruzione if (espressione3) { istruzione … … . } } } Fondamenti di java if (i < 100) { if (i > 0) System.out.println ("minore di 100 e maggiore di zero"); } else System.out.println ("maggiore o uguale a 100"); 6 Roberto Vergallo 3 12/10/16 Le strutture di controllo (cont.) Catene if-else-if Sintassi: ■ La forma più comune di if annidati è rappresentata dalla sequenza o catena if else-if. Questo tipo di concatenazione valuta una serie arbitraria di istruzioni booleane precedendo dall’alto verso il basso. Se almeno una delle condizioni restituisce il valore true verrà eseguito il blocco di istruzioni relativo. Se nessuna delle condizioni si dovesse verificare allora verrebbe eseguito il blocco else finale. 7 Fondamenti di java if(espressione) { istruzione } else if (espressione2) { istruzione } else if (espressione3) { istruzione … … . } else { istruzione … … . } Roberto Vergallo Le strutture di controllo (cont.) L’istruzione switch ■ Java mette a disposizione una istruzione di controllo di flusso che, specializzando la catena if-else-if, semplifica la vita al programmatore. L’istruzione switch è utile in tutti quei casi in cui sia necessario decidere tra opzioni multiple prese in base al controllo di una sola variabile. int i = getUserSelection(); if(i==1) { faiQualcosa(); } else if(i==2) { faiQualcosAltro(); } else { nonFareNulla (); } Fondamenti di java int i = getUserSelection(); switch (i) { case 1: faiQualcosa(); break; case 2: faiQualcosAltro(); break; default: nonFareNulla(); } 8 Sintassi: switch (espressione) { case espr_costante: istruzione1 break_opzionale case espr_costante: istruzione2 break_opzionale case espr_costante: istruzione3 break_opzionale … … … … .. default: istruzione4 } Roberto Vergallo 4 12/10/16 Le strutture di controllo (cont.) L’istruzione switch (cont.) In generale, dopo che viene valutata l’espressione di switch, il controllo della applicazione salta al primo case tale che espressione ==espr_costante ed esegue il relativo blocco di codice. Nel caso in cui il blocco sia terminato con una istruzione break, l’applicazione abbandona l’esecuzione del blocco switch saltando alla prima istruzione successiva al blocco, altrimenti il controllo viene eseguito sui blocchi case a seguire. Se nessun blocco case soddisfa la condizione Ossia espressione != espr_costante la virtual machine controlla l’esistenza della label default ed esegue, se presente, solo il blocco di codice relativo ed esce da switch. 9 Fondamenti di java Roberto Vergallo Le strutture di controllo (cont.) L’istruzione while ■ Una istruzione while permette l’esecuzione ripetitiva di una istruzione utilizzando una espressione booleana per determinare se eseguire il blocco di istruzioni, eseguendolo quindi fino a che l’espressione booleana non restituisce il valore false. ■ Per prima cosa, una istruzione while controlla il valore dell’espressione booleana. Se restituisce true verrà eseguito il blocco di codice di while. Alla fine dell’esecuzione viene nuovamente controllato il valore dell’espressione booleana per decidere se ripetere l’esecuzione del blocco di codice o passare il controllo dell’esecuzione alla prima istruzione successiva al blocco while. Sintassi: int i=0; while(i<10) { j=10; while(j>0) { System.out.println(“i=”+i+”e j=”+j); j--; } i++; } while (espressione_booleana){ istruzione } Fondamenti di java 10 Roberto Vergallo 5 12/10/16 Le strutture di controllo (cont.) L’istruzione do-while ■ Una alternativa alla istruzione while è rappresentata dall’istruzione do-while a differenza della precedente, controlla il valore della espressione booleana alla fine del blocco di istruzioni. In questo caso quindi il blocco di istruzioni verrà eseguito sicuramente almeno una volta. Sintassi: do { istruzione; } while (espressione_booleana); 11 Fondamenti di java Roberto Vergallo Le strutture di controllo (cont.) L’istruzione for ■ L'istruzione for può essere considerata come una versione estesa dell'istruzione while dove la fase di inizializzazione e la fase di modifica della variabile, o delle variabili che controllano il ciclo, sono espresse esplicitamente come parte dell'istruzione for (int i=0 ; i<10 ; i++) faiQualcosa(); Sintassi: for (inizializzazione; valore-booleano; incremento) istruzione; ■ La prima, istruzione di inizializzazione, viene eseguita una sola volta prima di entrare nel ciclo, la seconda, condizione d’uscita, viene valutata prima di ogni iterazione, analogamente alla condizione di uscita del while, mentre la terza, istruzione d’incremento, viene eseguita al termine del corpo del ciclo, giusto prima di una nuova valutazione della condizione d'uscita. Fondamenti di java 12 Roberto Vergallo 6 12/10/16 Le strutture di controllo (cont.) Istruzioni di ramificazione ■ Il linguaggio Java consente l’uso di tre parole chiave che consentono di modificare in qualunque punto del codice il normale flusso dell’esecuzione dell’applicazione con effetto sul blocco di codice in esecuzione o sul metodo corrente. Queste parole chiave sono tre (come schematizzato nella tabella seguente) e sono dette istruzioni di “branching” o ramificazione. 13 Fondamenti di java Roberto Vergallo Le strutture di controllo (cont.) L’istruzione break ■ Questa istruzione consente di forzare l’uscita da un ciclo aggirando il controllo sulla espressione booleana e provocandone l’uscita immediata in modo del tutto simile a quanto già visto parlando della istruzione switch. ■ L’istruzione break viene utilizzata in quei casi in cui risulta conveniente controllare la condizione d’uscita in momenti differenti dall’inizio o dalla fine del ciclo. int i = getUserSelection(); Notare come l’istruzione break aumenta l’efficienza del codice scritto, ma non sempre risulta strettamente necessario alla sua corretta esecuzione Fondamenti di java 14 switch (i) { case 1: faiQualcosa(); break; case 2: faiQualcosAltro(); break; default: nonFareNulla();} Roberto Vergallo 7 12/10/16 Le strutture di controllo (cont.) L’istruzione continue ■ A differenza del caso precedente questa istruzione non interrompe l’esecuzione del ciclo di istruzioni, ma al momento della chiamata produce un salto alla parentesi graffa che chiude il blocco restituendo il controllo alla espressione booleana che ne determina l’esecuzione. int i=-1; int pairs=0; while(i<20) { i++; if((i%2)!=0) continue; pairs ++; } Le righe di codice descritte calcolano quante occorrenze di interi pari ci sono in una sequenza di interi compresa tra 1 e 20 e memorizzano il valore in una variabile di tipo int chiamata “pairs”. Il ciclo while è controllato dal valore della variabile i inizializzata a –1. La riga 6 effettua un controllo sul valore di i: nel caso in cui i rappresenti un numero intero dispari viene eseguito il comando continue ed il flusso ritorna alla riga 3. In caso contrario viene aggiornato il valore di pairs. 15 Fondamenti di java Roberto Vergallo Le strutture di controllo (cont.) L’istruzione return Questa istruzione rappresenta l’ultima istruzione di ramificazione e può essere utilizzata per terminare l’esecuzione del metodo corrente tornando il controllo al metodo chiamante. Return può essere utilizzata in due forme: return valore; return; La prima forma viene utilizzata per consentire ad un metodo di ritornare valori al metodo chiamante e pertanto deve ritornare un valore compatibile con quello dichiarato nella definizione del metodo. La seconda può essere utilizzata per interrompere l’esecuzione di un metodo qualora il metodo ritorni un tipo void. Fondamenti di java 16 Roberto Vergallo 8 12/10/16 Le strutture di controllo (cont.) L’istruzione break con etichetta ■ L’istruzione break provoca l’uscita da una singola struttura while, for, do/ while o switch. Per uscire da un insieme di strutture nidificate, invece, è possibile utilizzare l’istruzione break con etichetta che, quando viene eseguita in una struttura while, for, do/ while o switch, provoca l’uscita immediata da quella struttura e da un qualsiasi numero di strutture iterative ivi racchiuse. ■ In questi casi, l’esecuzione del programma riprende con la prima istruzione dopo l’istruzione composta con etichetta (ovvero un gruppo di istruzioni composte tra parentesi graffe e precedute da etichetta) search: for (i = 0; i < arrayOfInts.length; i++) { for (j = 0; j < arrayOfInts[i].length; j++) { if (arrayOfInts[i][j] == searchfor) { foundIt = true; break search; } } } 17 Fondamenti di java Roberto Vergallo Costruttori ■ Un oggetto Java viene sempre creato tramite un metodo speciale detto costruttore ■ Ogni classe ha uno o piu` costruttori class ContoCorrente { ContoCorrente() { // generico } ContoCorrente(Persona richiedente) { // intestato } } Fondamenti di java 18 Roberto Vergallo 9 12/10/16 Package ■ L’idea originale (Common Lisp) è quella di un sistema per organizzare i simboli ■ nomi comuni come ad esempio “Persona” sono facilmente usati in più programmi ■ i package possone essere utilizzati per contestualizzare il nome di una classe package it.unisalento; Persona package it.ministeroDelleFinanze; package it.unile.admin; Persona Dipendente Contribuente Studente Fondamenti di java 19 Roberto Vergallo Package Java ■ I package sono meccanismi per raggruppare definizioni di classe in librerie. ■ Il meccanismo è provvisto di una struttura gerarchica per l’assegnamento di nomi alle classi in modo da evitare eventuali collisioni in caso in cui alcuni programmatori usino lo stesso nome per differenti definizioni di classe. ■ Le classi possono essere mascherate all’interno dei package implementando l’incapsulamento anche a livello di file. ■ Le classi di un package possono condividere dati e metodi con classi di altri package ■ I package forniscono un meccanismo efficace per distribuire oggetti Fondamenti di java 20 Roberto Vergallo 10 12/10/16 Package Java (cont.) ■ I package combinano definizioni di classi in un unico archivio la cui struttura gerarchica rispetta quella dei file system. ■ I nomi dei package sono separati tra loro da punto. La classe Vector ad esempio fa parte del package java.util archiviato nel file tools.jar ■ Secondo le specifiche, il linguaggio riserva tutti i package che iniziano con java per le classi che sono parte del linguaggio. Ciò vuol dire che nuove classi definite da un utente devono essere raggruppate in package con nomi differenti da questo. ■ Le specifiche suggeriscono inoltre che package generati con classi di uso generale debbano iniziare con il nome dell’azienda proprietaria del codice. Ad esempio se la pippo corporation avesse generato un insieme di classi dedicate al calcolo statistico, le classi dovrebbero essere contenute in un package chiamato ad esempio pippo.stat Fondamenti di java 21 Roberto Vergallo Package Java (cont.) ■ Una volta definito il nome di un package, affinché una classe possa essere archiviata al suo interno, è necessario aggiungere una istruzione package all’inizio del codice sorgente che definisce la classe. Per esempio all’inizio di ogni file contenente i sorgenti del package pippo.stat è necessario aggiungere la riga: package pippo.stat; questa istruzione non deve assolutamente essere preceduta da nessuna linea di codice. ■ In generale, se una classe non viene definita come appartenente ad un package, il linguaggio per definizione assegna la classe ad un particolare package senza nome. Fondamenti di java 22 Roberto Vergallo 11 12/10/16 Package (2) ■ L’idea originale (Common Lisp) è di un sistema di organizzazione dei simboli: – si usa quindi una notazione qualificata composta da un prefisso e da un simbolo esempio: it.unisalento.Persona – la pseudo-istruzione package definisce il package di riferimento – la pseudo-istruzione import serve ad abbreviare i riferimenti simbolici package it.unisalento.esercitazioniPPS; import it.unisalento.Persona; class StudenteDelCorsoPPS { Persona p; ... } 23 Fondamenti di java Roberto Vergallo Packages & directories ■ In Java il sistema dei package è anche un modo per organizzare le classi (sia .java che .class): – la struttura del prefisso viene trasformata in percorso nel file system : it.unisalento.Persona diventa $CLASSPATH/it/unisalento/Persona (.java o .class) – i classloader della macchina virtuale (i.e. java) e del compilatore (i.e javac) usano le stesse convenzioni. Fondamenti di java 24 Roberto Vergallo 12 12/10/16 Protezioni ■ L’accesso alle entità di classe o di istanza può essere protetto ■ In Java vi sono quattro livelli di protezione e tre parole chiave: – public – protected – private accesso senza restrizioni solo nello stesso package o nelle sottoclassi solo nella classe class ContoCorrente { private float saldo; ... float saldo(Persona richiedente) { if (richiedente.autorizzato()) return saldo; else class MountainBike { void cambiaRapporto(int r) { attivaProtezione(); super.cambiaRapporto(); disattivaProtezione(); } private void attivaProtezione() {...} nega informazione } } } private void disattivaProtezione() {...} 25 Fondamenti di java Roberto Vergallo Protezioni: esempio class Automobile { // attributi di classe static int numeroDiRuote = 4; static public boolean haTarga = true; static private Vector archivio; // attributi di istanza public String marca; public String colore; public int annoDiImmatricolazione; public String targa; public int numero DiCavalli; protected Persona titolare; private int rapporto; // metodi di classe static protected void inserisciInArchivioAutoveicoli(Automobile a) { archivio.addElement(a); } ... // metodi di istanza public void cambiaRapporto(int r) { ... rapporto = r; } public int rapporto() { return rapporto; }.... ... } Fondamenti di java 26 Roberto Vergallo 13 12/10/16 Modificatore public ■ Di default, la definizione di una classe Java può essere utilizzata solo dalle classi all’interno del suo stesso package. Per esempio, assumiamo di aver scritto un’applicazione in un file App.java non appartenente a nessun package e, supponiamo che esista una classe Stack appartenente al package app.stack. Per definizione, App.java non potrà accedere alla definizione di classe di Stack. Package app.stack; class Stack { int data[]; int ndata; void push(int i) { … } int pop() { … } } Fondamenti di java Package app.stack; Public class Stack { int data[]; int ndata; void push(int i) { … } int pop() { … } } 27 Roberto Vergallo Istruzione import ■ Il runtime di Java fornisce un ambiente completamente dinamico. Le classi non vengono caricate fino a che non sono referenziate per la prima volta durante l’esecuzione dell’applicazione. ■ Dal momento che le classi possono essere organizzate in package, è necessario specificare a quale package una classe appartenga pena l’incapacità della virtual machine di trovarla. ■ Un modo per indicare il package a cui una classe appartiene è quello di specificare il package ad ogni chiamata alla classe ossia utilizzando nomi qualificanti. Riprendendo la classe Stack appartenente al package app.stack, il suo nome qualificante sarà app.stack.Stack ■ L’uso dei nomi qualificanti non è sempre comodo soprattutto per package organizzati con gerarchie a molti livelli. Per venire incontro al programmatore, Java consente di specificare una volta per tutte il nome qualificato di una classe all’inizio del file utilizzando la parola chiave import Fondamenti di java 28 Roberto Vergallo 14 12/10/16 Istruzione import (cont.) ■ L’istruzione import ha come unico effetto quello di identificare univocamente una classe e quindi di consentire al compilatore di risolvere nomi di classe senza ricorrere ogni volta a nomi qualificanti import app.stack.Stack; ■ Capita spesso di dover utilizzare un gran numero di classi appartenenti ad un unico package. Per questi casi l’istruzione import supporta l’uso di un carattere fantasma che risolve il nome di tutte le classi pubbliche di un package import app.stack.*; import app.stack.S*: //non è consentito Fondamenti di java 29 Roberto Vergallo 15