Introduzione a Java Richiami Cenni sull Implementazione Macchine

  • Slides: 65
Download presentation
Introduzione a Java

Introduzione a Java

Richiami • Cenni sull’ Implementazione, Macchine Astratte, Compilatore, Interprete • Ruolo delle Classi in

Richiami • Cenni sull’ Implementazione, Macchine Astratte, Compilatore, Interprete • Ruolo delle Classi in Java

Implementare un linguaggio • implementazione un linguaggio L su una macchina ospite MO •

Implementare un linguaggio • implementazione un linguaggio L su una macchina ospite MO • realizzare la macchina astratta ML sulla macchina ospite MO • tipicamente L linguaggio ad alto livello • MO esegue un linguaggio piu’ a basso livello (e. g. linguaggio macchina, assembler)

Macchina Astratta § ML una collezione di strutture dati ed algoritmi in grado di

Macchina Astratta § ML una collezione di strutture dati ed algoritmi in grado di memorizzare ed eseguire programmi di L §componenti della macchina astratta interprete lmemoria (dati e programmi) lcontrollo loperazioni “primitive” (del linguaggio della macchina ospite) l

Macchina astratta Memoria Interprete Programma Dati Controllo Operazioni primitive op 1 op 2 …

Macchina astratta Memoria Interprete Programma Dati Controllo Operazioni primitive op 1 op 2 … . . . opn

L’interprete start acquisisci la prossima istruzione controllo decodifica acquisisci gli operandi controllo seleziona operazioni

L’interprete start acquisisci la prossima istruzione controllo decodifica acquisisci gli operandi controllo seleziona operazioni controllo esegui op 1 esegui op 2 . . . esegui opn memorizza il risultato esegui alt stop

Dal linguaggio alla macchina astratta • L linguaggio ML macchina astratta di L •

Dal linguaggio alla macchina astratta • L linguaggio ML macchina astratta di L • implementazione di L = realizzazione di ML su una macchina ospite MO • se L è un linguaggio ad alto livello ed MO è una macchina “fisica” – l’interprete di ML è necessariamente diverso dall’interprete di MO – come si implementa?

Implementare un linguaggio • implementazione di L 1: interprete (puro) – ML è realizzata

Implementare un linguaggio • implementazione di L 1: interprete (puro) – ML è realizzata su MO in modo interpretativo – scarsa efficienza, soprattutto per colpa dell’interprete (ciclo di decodifica) • implementazione di L 2: compilatore (puro) – i programmi di L sono tradotti in programmi funzionalmente equivalenti nel linguaggio macchina di MO – i programmi tradotti sono eseguiti direttamente su MO • ML non viene realizzata – il problema è quello della dimensione del codice prodotto • due casi limite che nella realtà non esistono quasi mai: c’è sempre una macchina intermedia che estende eventualmente la macchina ospite in alcuni componenti

Implementazione mista ML MI Programma in L realizzazione MO Programma in LMI traduzione •

Implementazione mista ML MI Programma in L realizzazione MO Programma in LMI traduzione • quando l’interprete della macchina intermedia MI non coincide con quello della macchina ospite MO • esiste un ciclo di interpretazione del linguaggio intermedio LMI realizzato su MO

Interpretazione e traduzione pure ML MI Programma in L realizzazione MO Programma in LMI

Interpretazione e traduzione pure ML MI Programma in L realizzazione MO Programma in LMI traduzione • Casi limite (possibili solo se i linguaggi sono molto vicini) • ML = MI interpretazione pura • MO = MI traduzione pura

Implementazioni miste: vantaggi – per ottenere un codice tradotto più compatto – per facilitare

Implementazioni miste: vantaggi – per ottenere un codice tradotto più compatto – per facilitare la portabilità su diverse macchine ospiti • si deve riimplementare l’interprete del linguaggio intermedio • non è necessario riimplementare il traduttore – su una tipica macchina ospite e’ piu’ semplice realizzare l’interprete per ill linguaggio intermedio (piu’ vicino al linguaggio della macchina ospite).

L’implementazione di Java • è un’implementazione mista – traduzione dei programmi da Java a

L’implementazione di Java • è un’implementazione mista – traduzione dei programmi da Java a byte-code, linguaggio macchina di una macchina intermedia chiamata Java Virtual Machine – i programmi byte-code sono interpretati

Vantaggi • su una tipica macchina ospite, è più semplice realizzare l’interprete di byte-code

Vantaggi • su una tipica macchina ospite, è più semplice realizzare l’interprete di byte-code che l’interprete di Java • byte-code piu’ a basso livello

Vantaggi • inoltre si possono effettuare una volta per tutte (a tempo di traduzione,

Vantaggi • inoltre si possono effettuare una volta per tutte (a tempo di traduzione, staticamente) analisi, verifiche e ottimizzazioni che migliorano – l’affidabilità dei programmi (assenza di errori run-time) – l’efficienza dell’esecuzione (meno controlli run-time) • varie proprietà interessate – controllo dei tipi – controllo sull’uso dei nomi e loro risoluzione “statica” – ….

Analisi statica in Java • Java è fortemente tipato – il type checking può

Analisi statica in Java • Java è fortemente tipato – il type checking può essere in gran parte effettuato dal traduttore e sparire quindi dal byte-code generato • come vedremo pero’ le relazioni di subtyping permettono che una entità abbia un tipo vero (tipo effettivo) diverso da quello apparente (tipo apparente) • di conseguenza, alcune questioni legate ai tipi possono solo essere risolte a tempo di esecuzione – possono verificarsi errori di tipo a tempo di esecuzione rilevati da opportune eccezione

Ruolo delle classi in Java § I programmi in Java consistono di classi. §

Ruolo delle classi in Java § I programmi in Java consistono di classi. § Le classi consentono di definire: • collezioni di procedure stand-alone (metodi statici) • nuovi tipi di dato, tramite oggetti (in cui variabili e metodi d’istanza definiscono lo stato interno e le operazioni)

Ruolo delle classi in Java • Le due funzionalita’ possono coesistere all’interno di una

Ruolo delle classi in Java • Le due funzionalita’ possono coesistere all’interno di una stessa classe • Una classe puo’ contenere variabili statiche d’istanza • Analogo per i metodi

Procedure Stand-alone • Le classi permettono di definire collezione di metodi statici (procedure stand

Procedure Stand-alone • Le classi permettono di definire collezione di metodi statici (procedure stand alone) • non ci sono dichiarazioni di variabili e metodi d’istanza • non si definiscono oggetti

public class Proc. Arrays{ //OVERVIEW: la classe fornisce procedure utili per // manipolare arrays

public class Proc. Arrays{ //OVERVIEW: la classe fornisce procedure utili per // manipolare arrays di interi public static int cerca(int [] a, int x){ \EFFECTS: restituisce il numero di occorrenze di x in a int occ=0; for (int i = 0; i< a. length ; i++) {if (a[i]=x) {occ=occ+1; } } return occ; } public static boolean incr(int [] a){ \EFFECTS: restituisce true se a e’ ordinato in modo crescente int prev; for (int i = 1; i< a. length ; i++) {prev=a[i-1]; if (prev> a[i]) { return false; } } return true; } }

Metodi statici • I metodi statici appartengono alla classe in cui sono dichiarati •

Metodi statici • I metodi statici appartengono alla classe in cui sono dichiarati • Si chiamano tramite il riferimento alla classe

Esempio: main. . . . int[] a= new int[10]; int x=0; for (int i

Esempio: main. . . . int[] a= new int[10]; int x=0; for (int i = 0; i< a. length ; i++) {a{i}=x; x=x+1; } boolean result=Proc. Arrays. incr(a); . . . .

Tipi di dato • Le classi permettono di creare nuovi tipi di dato ----collezioni

Tipi di dato • Le classi permettono di creare nuovi tipi di dato ----collezioni di dati ----relative operazioni • Lo stato degli oggetti e’ definito dalle variabili d’istanza • Le operazioni dai metodi d’istanza

Esempio tipico • Vogliamo realizzare una classe Bank. Account i cui oggetti sono dei

Esempio tipico • Vogliamo realizzare una classe Bank. Account i cui oggetti sono dei semplici conti bancari. • Vogliamo le seguenti operazioni q depositare denaro q prelevare denaro q chiedere il saldo corrente

Come si procede? • Variabili d’istanza per rappresentare lo stato degli oggetti • Metodi

Come si procede? • Variabili d’istanza per rappresentare lo stato degli oggetti • Metodi d’istanza per modellare le operazioni richieste • Costruttore (o costruttori) per creare un nuovo oggetto della classe ed inizializzare le variabili

Una possibile implementazione public class Bank. Account { public double balance; //il saldo corrente

Una possibile implementazione public class Bank. Account { public double balance; //il saldo corrente // costruttore public Bank. Account(double initial){ balance=initial; }

Una possibile implementazione // metodi public void deposit(double amount) { balance = balance +

Una possibile implementazione // metodi public void deposit(double amount) { balance = balance + amount; } public void withdraw(double amount) { balance = balance - amount; } public double get. Balance() { return balance; } }

Creare oggetti • Gli oggetti istanze della classe si creano tramite new • Hanno

Creare oggetti • Gli oggetti istanze della classe si creano tramite new • Hanno il tipo nome della classe Bank. Account p 1= new Bank. Account(1000); • p 1 e’ dichiarato con tipo Bank. Account • La variabile balance dell’oggetto riferito da p 1 viene inizializzata al valore 1000

Variabili d’istanza • Le variabili d’istanza appartengono agli oggetti • Ogni oggetto ha la

Variabili d’istanza • Le variabili d’istanza appartengono agli oggetti • Ogni oggetto ha la propria variabile d’istanza balance, il cui valore e’ memorizzato nella heap Bank. Account p 1= new Bank. Account(1000); Bank. Account p 2=new Bank. Account(2000); • La variabile balance dell’oggetto riferito da p 1 viene inizializzata al valore 1000 • La variabile balance dell’oggetto riferito da p 2 viene inizializzata al valore 2000

Come si accede agli oggetti? • Per leggere/ modificare lo stato interno rappresentato dalle

Come si accede agli oggetti? • Per leggere/ modificare lo stato interno rappresentato dalle variabili d’istanza • Tramite le relative operazioni (metodi d’istanza) • Accedendo direttamente allo stato interno, alle variabili d’istanza • In entrambi i casi deve essere specificato l’oggetto sul quale si vuole operare

Esempio Bank. Account p 1= new Bank. Account(1000); Bank. Account p 2=new Bank. Account(2000);

Esempio Bank. Account p 1= new Bank. Account(1000); Bank. Account p 2=new Bank. Account(2000); • Vogliamo trasferire 1000 dal conto di p 1 in quello di p 2

Prima soluzione Bank. Account p 1= new Bank. Account(1000); Bank. Account p 2=new Bank.

Prima soluzione Bank. Account p 1= new Bank. Account(1000); Bank. Account p 2=new Bank. Account(2000); p 1. withdraw(1000); p 2. deposit(1000); • I metodi d’istanza vanno invocati fornendo il riferimento all’oggetto su cui si vuole effettuare l’operazione

Seconda soluzione Bank. Account p 1= new Bank. Account(1000); Bank. Account p 2=new Bank.

Seconda soluzione Bank. Account p 1= new Bank. Account(1000); Bank. Account p 2=new Bank. Account(2000); p 1. balance=0; p 2. balance=balance+1000; • Per accedere alle variabili d’istanza bisogna fornire il riferimento all’oggetto su cui si vuole effettuare l’operazione

ATTENZIONE: Specificatore di Accesso • public (si puo’ accedere da qualsiasi metodo della classe

ATTENZIONE: Specificatore di Accesso • public (si puo’ accedere da qualsiasi metodo della classe o non ) • private (si puo’ accedere solo da metodi della classe)

Esempio • Supponiamo che balance sia private allora il seguente accesso dal metodo main

Esempio • Supponiamo che balance sia private allora il seguente accesso dal metodo main non sarebbe legale (viene rilevato dal compilatore) Bank. Account p 1= new Bank. Account(1000); Bank. Account p 2=new Bank. Account(2000); p 1. balance=0; p 2. balance=balance+1000;

Ruolo di private • Come vedremo e’ sempre consigliabile sempre usare -- variabili d’istanza

Ruolo di private • Come vedremo e’ sempre consigliabile sempre usare -- variabili d’istanza private --introdurre metodi d’istanza per leggere e modificare opportunamente lo stato degli oggetti • In questo modo si crea un incapsulamento degli oggetti che possono essere modificati solo dai metodi d’istanza • Fondamentale per programmare in modo modulare e per garantire un corretto funzionamento

Esempio 1 Bank. Account p 1= new Bank. Account(1000); Bank. Account p 2=new Bank.

Esempio 1 Bank. Account p 1= new Bank. Account(1000); Bank. Account p 2=new Bank. Account(2000); p 1. withdraw(1000); p 2. deposit(1000); • Questo codice che accede agli oggetti solo tramite metodi d’istanza e’ indipendente dall’implementazione interna della classe Bank. Account • Se cambia l’implementazione continua a funzionare

Esempio 2 Bank. Account p 1= new Bank. Account(1000); Bank. Account p 2=new Bank.

Esempio 2 Bank. Account p 1= new Bank. Account(1000); Bank. Account p 2=new Bank. Account(2000); p 1. balance=0; p 2. balance=balance+1000; • Questo codice accede dipende dallo stato interno della classe Bank. Account • Se cambia l’implementazione deve essere reimplementato (non e’ un esempio di buona programmazione)

Attenzione • I metodi d’istanza devono essere chiamati con il riferimento all’oggetto • Questo

Attenzione • I metodi d’istanza devono essere chiamati con il riferimento all’oggetto • Questo riferimento puo’ anche essere implicito se siamo in un metodo d’istanza o costruttore della classe

Riferimento Implicito public class Bank. Account{ public double balance; //il saldo corrente // costruttore

Riferimento Implicito public class Bank. Account{ public double balance; //il saldo corrente // costruttore public Bank. Account(double initial){ balance=initial; } • Il riferimento e’ all’oggetto di tipo Bank. Account su cui stiamo eseguendo il metodo d’istanza (analogogo this. balance)

Metodi e Variabili Statici • Variabili e metodi statici appartengono alla classe in cui

Metodi e Variabili Statici • Variabili e metodi statici appartengono alla classe in cui sono dichiarati • A differenza delle variabili e dei metodi di istanza che appartengono agli oggetti (istanze della classe) • Sono quindi condivisi tra tutti gli oggetti della classe • Come vedremo nella semantica stanno nell’ambiente delle classi e non nella heap

A cosa servono? • A memorizzare informazioni comuni tra tutti gli oggetti istanze della

A cosa servono? • A memorizzare informazioni comuni tra tutti gli oggetti istanze della classe • A realizzare funzionalita’ indipendenti dagli oggetti • Come vedremo nella semantica formale le informazioni sulle variabili e sui metodi statici saranno memorizzate proprio nell’ambiente delle classi

Esempio: var. statiche • Supponiamo di volere modificare Bank. Account in modo che ogni

Esempio: var. statiche • Supponiamo di volere modificare Bank. Account in modo che ogni conto abbia un codice identificativo, ognuno diverso dagli altri • Si puo’ utilizzare una variabile statica che mantiene il valore del primo numero intero disponibile • Introduciamo anche un metodo statico per inizializzare il valore della variabile statica

Una possibile implementazione public class Bank. Account { public double balance; //il saldo corrente

Una possibile implementazione public class Bank. Account { public double balance; //il saldo corrente public int miocodice; //il codice del conto public static int codice; //il primo codice disponibile • La variabile statica codice e’ unica e condivisa tra tutti i conti • Viene aggiornata ogni volta che viene creato un oggetto • La variabile d’istanza miocodice mantiene invece il codice dei singoli conti

Costruttore public Bank. Account(double initial){ balance=initial; miocodice=codice; codice++; } • La variabile statica e’

Costruttore public Bank. Account(double initial){ balance=initial; miocodice=codice; codice++; } • La variabile statica e’ unica e condivisa tra tutti i conti • Viene incrementata ogni volta che viene creato un nuovo conto • In questo modo mantiene sempre aggiornato il primo valore libero

Metodo statico public static void modifica-codice(int val){ \REQUIRES: val >= codice=val; } • Permette

Metodo statico public static void modifica-codice(int val){ \REQUIRES: val >= codice=val; } • Permette di inizializzare la variabile statica e di aggiornarne il valore (con un valore piu’ grande)

Esempio Bank. Account. modifica-codice(10); Bank. Account p 1= new Bank. Account(1000); Bank. Account p

Esempio Bank. Account. modifica-codice(10); Bank. Account p 1= new Bank. Account(1000); Bank. Account p 2=new Bank. Account(2000); • La variabile statica codice prende inizialmente il valore 10 • I due oggetti avranno codici diversi e la loro creazione modifichera’ il valore di codice • Notate che al solito il metodo statico deve essere chiamato tramite il riferimento alla classe

Specificatori di accesso • Valgono le stesse regole viste per le variabili ed i

Specificatori di accesso • Valgono le stesse regole viste per le variabili ed i metodi di istanza

Variabili e Metodi Statici: come si accede? • Supponiamo per esempio di essere in

Variabili e Metodi Statici: come si accede? • Supponiamo per esempio di essere in un metodo esterno alla classe (tipo main) e che la variabile sia public (anche se non ha senso da un punto di vista di sicurezza) • Come facciamo a riferirci alla variabile codice ? Bank. Account. codice=1;

Regole di Visibilita’ dei Nomi • Sono quelle verificate staticamente dal compilatore (si chiamano

Regole di Visibilita’ dei Nomi • Sono quelle verificate staticamente dal compilatore (si chiamano regole di scoping) • Verifica che ogni accesso ad un nome (di variabile o metodo) sia legale, ovvero che ci sia un legame corretto tra le dichiarazioni e l’uso dei nomi

Perche’ ci interessa? • Vogliamo estendere la semantica di FP al caso di classi

Perche’ ci interessa? • Vogliamo estendere la semantica di FP al caso di classi Java piu’ generali --dichiarazioni di variabili e metodi statici --dichiarazioni di variabili e metodi d’istanza • La situazione e’ un po’ piu’ complicata di quella che avete visto fino ad ora (erano semplificate a scopo didattico)

In particolare • Cerchiamo di capire come funziona a livello intuitivo la ricerca dei

In particolare • Cerchiamo di capire come funziona a livello intuitivo la ricerca dei nomi • Tralasciando per ora di trattare gli specificatori d’accesso (assumiamo che le dichiarazioni siano tutte public) • Poi, introdurremo le strutture dello stato e le regole formali della semantica

Problema • Nel codice di un metodo abbiamo un accesso del seguente tipo Path.

Problema • Nel codice di un metodo abbiamo un accesso del seguente tipo Path. I variabile Path. I(List. P) chiamata di metodo I identificatore o nome Path ci dice dove andare a cercarlo

Problema • Come facciamo a sapere se questo tipo di istruzione e’ legale? •

Problema • Come facciamo a sapere se questo tipo di istruzione e’ legale? • Ovvero: dove andiamo a cercare il valore della variabile o il codice del metodo Path. I variabile Path. I(List. P) chiamata di metodo

Nota • E’ complicato perche’ I potrebbe essere statico o d’istanza o potrebbe essere

Nota • E’ complicato perche’ I potrebbe essere statico o d’istanza o potrebbe essere una variabile locale del metodo • Dipende dal Path e dal tipo di metodo (statico o d’istanza)

Cosa puo’ indicare un path? • Accesso diretto (path vuoto) I • Riferimento ad

Cosa puo’ indicare un path? • Accesso diretto (path vuoto) I • Riferimento ad un oggetto this. I p 1. I • Riferimento ad una classe Bank. Account. I

Per semplificare • Vediamo le regole per le variabili • Per i metodi e’

Per semplificare • Vediamo le regole per le variabili • Per i metodi e’ analogo

Path Vuoto I potrebbe essere • una variabile locale o un parametro formale del

Path Vuoto I potrebbe essere • una variabile locale o un parametro formale del metodo • una variabile che appartiene alla classe (se il metodo e’ statico) • una variabile che si vede dall’oggetto su cui il metodo e’ eseguito (se il metodo e’ d’istanza o e’ un costruttore)

Primo caso • una variabile locale o un parametro formale del metodo public Bank.

Primo caso • una variabile locale o un parametro formale del metodo public Bank. Account(double initial){ balance=initial; miocodice=codice; codice++; }

Cosa e’ visibile da un oggetto? • Le sue variabili d’istanza • Le variabili

Cosa e’ visibile da un oggetto? • Le sue variabili d’istanza • Le variabili statiche dichiarate nella classe a cui appartiene (perche’ sono condivise tra tutti gli oggetti)

Costruttore public Bank. Account(double initial){ balance=initial; miocodice=codice; codice++; } • Accesso diretto alla variabile

Costruttore public Bank. Account(double initial){ balance=initial; miocodice=codice; codice++; } • Accesso diretto alla variabile d’istanza miocodice (this non e’ necessario) si riferisce implicitamente a quella dell’oggetto creato • Accesso diretto alla variabile statica codice che e’ condivisa e visibile tra tutti gli oggetti della classe (Bank. Account non e’ necessario)

Cosa e’ visibile da una classe? • Le variabili statiche • Non sono visibili

Cosa e’ visibile da una classe? • Le variabili statiche • Non sono visibili variabili d’istanza (sono relative agli oggetti)

Metodo statico di Bank. Account public static void modifica-codice(int x){ codice=x; } • Accesso

Metodo statico di Bank. Account public static void modifica-codice(int x){ codice=x; } • Accesso diretto alla variabile statica codice che appartiene alla classe del metodo • Non potremo accedere direttamente alla variabile d’istanza miocodice (non ci sono oggetti di riferimento)

Path Classe • Vediamo quello che si vede dalla classe • Per esempio da

Path Classe • Vediamo quello che si vede dalla classe • Per esempio da main: Bank. Account. codice=1; (accesso legale) Bank. Account. balance=1; (accesso illegale)

Path Oggetto • Vediamo quello che si vede dall’oggetto • Per esempio da main:

Path Oggetto • Vediamo quello che si vede dall’oggetto • Per esempio da main: Bank. Account p 1=new Bankaccount(1000); p 1. codice=1; (accesso legale) p 1. balance=1; (accesso legale)

Conclusione • La coesistenza di nomi statici e d’istanza complica il linguaggio • Nelle

Conclusione • La coesistenza di nomi statici e d’istanza complica il linguaggio • Nelle prossime lezioni vedremo come estendere le regole della semantica di FP in modo da trattare espressioni del tipo Path. I(List. P)