TARDINI DEVIS MTR. 35212 1° ESERCITAZIONE DI LABORATORIO Questa esercitazione è stata tenuta al fine di prendere confidenza con il linguaggio di programmazione java, che è al centro di questo corso di Linguaggi e Traduttori. In seguito verrà presentata la realizzazione di un Counter (contatore), realizzato utilizzando più operazioni messe a disposizione dalla JDK. Per questi primi due programmi sorgente (Example.java e Counter.java) verrà presentata una versione che utilizza la peculiarità del package, dove per package si intende un gruppo di classi che costituiscono una unità concettuale, ed una versione che non la utilizza. Viene proposto di seguito il sorgente: Counter.java package ex1; /** * * A Counter is an object that counts integer values. * It provides services to be reset, * to be incremented and to retrieve its value * * @author Pippo Baudo * @version 1.0 */ public class Counter { /** * Resets the counter value. * * The value is reset to zero. */ public void reset(){ value=0; } /** * Increments the counter value. */ public void inc(){ value++; } /** * Gets the counter value. */ public int getValue(){ return value; } // private data private int value; } Come si può notare all’inizio del file è presente una dichiarazione di package: package ex1. Questo package di nome ex1, richiede che tutte le sue classi si trovino in una cartella di nome ex1. Compilando tramite l’apposito comando (javac) questo file, viene creata la classe pubblica Counter (public class Counter), in essa sono definite le operazioni pubbliche della medesima classe (reset, inc, getValue). Queste operazioni pubbliche sono così definite: reset: resetta il counter portandolo al valore iniziale 0; inc: incremente il counter di una unità; getValue: restituisce il valore attuale. Il campo value è privato, quindi può essere acceduto solo dalle operazioni definite nella medesima classe (reset, inc, getValue), e nessun altro; in questo modo si garantisce l’incapsulamento. Di seguito il file sorgente: Example.java package ex1; /** * Example application explaining * the use of Counter object */ public class Example { public static void main (String args[]) { Counter c= new Counter(); c.reset(); c.inc(); c.inc(); System.out.println(c.getValue()); } } La frase Counter c definisce un riferimento a counter (una specie di puntatore), l’oggetto counter viene poi creato dinamicamente tramite il comando new. L’oggetto referenziato, in questo caso Counter, è quindi direttamente accessibile tramite la notazione puntata: c.inc(); x = c.getValue(); Si ha quindi che questo programma è fatto di due classi, una che fa da componente software, e ha come compito quello di definire il main (solo parte statica) e l’altra invece implementa il tipo counter (parte non statica). A run-time nasce un oggetto: lo crea all’istante il main, quando vuole, tramite new, a immagine e somiglianza della classe Counter e poi lo usa per nome, con la notazione puntata, senza bisogno di dereferenziarlo esplicitamente. Nell’ordine vengono compilate le classi: javac Counter.java che produce il file Counter.class javac Example.java che produce il file Example.class la classe counter deve quindi già esistere quando si compila la classe Example. Per eseguire il programma basta invocare l’interprete con il nome di quella classe (pubblica) che contiene il main: java Example. Questa procedura sarebbe stata corretta se non avessimo specificato il package in quanto se una classe non dichiara di appartenere ad alcun package, automaticamente è assegnata al package di default, che per convenzione fa riferimento alla cartella corrente. Per compilare queste due classi mi sono dovuto mettere nella cartella superiore a ex1 ed invocare il compilatore con il percorso completo della classe: javac ex1/Counter.java javac ex1/Example.java in questo modo ho ottenuto i file.class . Anche per quanto riguarda l’esecuzione, ho dovuto agire nel medesimo modo: mi sono posto nella cartella superiore ad ex1 e da lì ho invocato l’interprete con il nome assoluto della classe: java ex1.Example Come risultato si ottiene la stampa a video del numero 2. Infatti se si legge il programma si può notare che inizialmente il contatore viene resettato e successivamente incrementato per ben due volte; dopodiché viene chiesto che venga restituito il valore così ottenuto e stampato a video su una linea. Viene esposto in seguito il medesimo programma senza l’utilizzo del package: Counter.java /** * * A Counter is an object that counts integer values. * It provides services to be reset, * to be incremented and to retrieve its value * * @author Pippo Baudo * @version 1.0 */ public class Counter { /** * Resets the counter value. * * The value is reset to zero. */ public void reset(){ value=0; } /** * Increments the counter value. */ public void inc(){ value++; } /** * Gets the counter value. */ public int getValue(){ return value; } // private data private int value; } Example.java /** * Example application explaining * the use of Counter object */ public class Example { public static void main (String args[]) { Counter c= new Counter(); c.reset(); c.inc(); c.inc(); System.out.println(c.getValue()); } } Questi due sorgenti rispetto ai precedenti non hanno specificato il package, per questo motivo cambiano le istruzioni da eseguire per la compilazione ed esecuzione, ma trattandosi di programmi identici il risultato finale che si ottiene è il medesimo. Se la classe Counter non fosse stata pubblica, le due classi avrebbero potuto essere scritte nel medesimo file.java, come viene proposto qui di seguito: Example.java package ex2; public class Example { public static void main (String args[]) { Counter c= new Counter(); c.reset(); c.inc(); c.inc(); System.out.println(c.getValue()); } } class Counter { public void reset(){ value=0; } public void inc(){ value++; } public int getValue(){ return value; } // private data private int value; } l’ordine delle classi nel file è irrilevante, non esiste un concetto di dichiarazione che deve precedere l’uso. Il file prende il nome da quello della classe pubblica, in questo caso Example.java . Compilando il file otteniamo comunque due file.class, uno per ogni singola classe compilata, ogni file.class rappresenta quella classe, in quanto un file non può contenere più classi. Il terzo esempio che qui di seguito verrà proposto serve a spiegare meglio il concetto di uguaglianza fra oggetti. Counter.java package ex3; /** * * A Counter is an object that counts integer values. * It provides services to be reset, * to be incremented and to retrieve its value * */ public class Counter { /** * Resets the counter value. * * The value is reset to zero. */ public void reset(){ value=0; } /** * Increments the counter value. */ public void inc(){ value++; } /** * Gets the counter value. */ public int getValue(){ return value; } /** * Tests if two counters are equal. * * Two counters are equal when they have * the same value. */ public boolean equals(Counter x){ return value==x.value; } // private data private int value; } Example.java package ex3; public class Example { public static void main (String args[]) { Counter c1 = new Counter(); c1.reset(); c1.inc(); System.out.println("c1 = "+c1.getValue()); Counter c2 = c1; c2.inc(); System.out.println("c1 = "+c1.getValue()); System.out.println("c2 = "+c2.getValue()); // Counter c3 = new Counter(); c3.inc(); System.out.println(c3.equals(c1)); c3.inc(); System.out.println(c3.equals(c1)); } } Esaminiamo il file Example.java, inizialmente viene creato il riferimento c1 per l’oggetto Counter, viene creato l’oggetto Counter, c1 viene prima resettato poi incrementato e successivamente visualizzato a video, a questo punto c1=1. Ora viene creato il riferimento c2 per l’oggetto Counter e assegnato a c1 (c2 = c1), in questo modo l’oggetto Counter referenziato è condiviso, c2 coincide con c1, quindi se si incrementa c2 risultano incrementati entrambi, tant’è vero che eseguendo il programma a questo punto, viene visualizzato a video c1 = 2 e c2 = 2. Viene creato il riferimento c3 per l’oggetto Counter, viene creato l’oggetto Counter, c3 viene incrementato. Ora verrà eseguita l’operazione pubblica equals, che è stata definita all’interno della classe Counter. Come si può vedere equals è stata definita in modo che vengano considerati uguali due Counter se e solo se hanno identico valore ed è proprio per questo che avendo c1 = 2 e c3 = 1, la richiesta di stampare a video l’equals tra c1 e c3 restituisce false. Successivamente c3 viene nuovamente incrementato, in questo modo ripetendo l’equals tra c1 e c3 viene restituito true. Nel esempio che segue vengono utilizzati dei costruttori per inizializzare l’oggetto Counter. Counter.java package ex4; /** * * A Counter is an object that counts integer values. * It provides services to be reset, * to be incremented and to retrieve its value * */ public class Counter { /** * Constructs a counter with default value (1). */ public Counter(){ value=1; } /** * Constructs a counter providing a start value. */ public Counter(int v){ value=v; } /** * Resets the counter value. * * The value is reset to zero. */ public void reset(){ value=0; } /** * Increments the counter value. */ public void inc(){ value++; } /** * Increments the counter value. * * @param n amount of the increment */ public void inc(int n){ value+=n; } /** * Gets the counter value. */ public int getValue(){ return value; } /** * Tests if two counters are equal. * * Two counters are equal when they have * the same value. */ public boolean equals(Counter x){ return value==x.value; } // private data private int value; } Example.java package ex4; public class Example { public static void main (String args[]) { Counter c1 = new Counter(); c1.inc(); Counter c2 = new Counter(10); c2.inc(); System.out.println("c1 = "+c1.getValue()); System.out.println("c2 = "+c2.getValue()); } } Nel file Counter.java sono stati definiti i costruttori, più precisamente con l’istruzione: public Counter(){ value=1; } Viene praticamente definito che alla creazione di un oggetto Counter se non viene passato in ingresso alcun parametro esso si inizializza automaticamente a 1. Mentre con l’istruzione: public Counter(int v){ value=v; } si definisce che alla crezione di un oggetto Counter, il valore int passato come parametro è il valore con il quale viene inizializzato il Counter. Compilando ed eseguendo i file, come risultato si ottiene la stampa a video del numero 2 e del numero 11. Questo guardando il file Example.java è facilmente deducibile. Viene creato l’oggetto Counter c1 il quale fa scattare il costruttore che lo inizializza a 1, successivamente viene incrementato. Viene creato l’oggetto Counter c2 il quale fa scattare il costruttore che lo inizializza a 10, successivamente viene incrementato. Viene stampato a video il valore di c1 che è 2 e il valore di c2 che è 11.