Ese 1 (del 31 Marzo 2004)
Il compilatore Non esegue il programma, non guarda i valori che possono assumere di volta in volta le variabili, non fa assunzioni sul flusso di controllo Fa solo una analisi statica (oltre a tradurre) Sapendo come e dove sono dichiarati variabili e metodi, esamina separatamente ogni istruzione controllando solo se e’ corretta rispetto: alle regole di visibilita’ dei nomi e al tipo Usa il tipo apparente, quello effettivo dipende dal valore (non si conosce e a causa dei sottotipi puo’ essere diverso)
Approssimazione L’analisi e’ approssimata (per forza), puo’ rilevare errori che non si verificherebbero (perche’ non fa assunzioni sul flusso di controllo) Viceversa e’ safe, se non trova errori, non ci saranno (a parte gli errori di tipo run-time dovuti ai cast) Perche’ si fa l’analisi statica? Per evitare il piu’ possibile i controlli run-time (esecuzione inefficiente) Ci sono linguaggi in cui non si fa il controllo dei tipi (e’ una scelta di progettazione)
Regole di scoping delle dichiarazioni Viste a lezione Implementate nella semantica (da fmet e naming)
Da una classe sono direttamente visibili nell’ordine i propri nomi statici e quelli delle superclassi I metodi statici hanno la visibilita’ della classe di appartenenza (quella in cui sono dichiarati), oltre ai nomi locali Non vediamo i nomi d’istanza, infatti sono indipendenti dagli oggetti (stand-alone) Variabili + metodi statici
Da un oggetto sono direttamente visibili nell’ordine i propri nomi d’istanza (inclusi quelli ereditati) e la classe, tramite questa le variabili statiche sue e delle superclassi Le variabili statiche sono infatti condivise tra tutti gli oggetti della classe o sottoclassi I metodi d’istanza (inclusi i costruttori) hanno la visibilita’ dell’oggetto su cui sono eseguiti, oltre alle variabili locali Variabili + metodi d’istanza
Identificare gli errori che verrebbero segnalati dal compilatore per le seguenti dichiarazioni di classe: public class Sopra { public static int a; public int [] c; public static void metodo1(int i) { a=i; return;} public Sopra metodo2(int i) { Sopra w=new Sopra(); metodo1(3); w.c[i]=a; c[i]=a;return w;} {a=12; c=new int[6];} } public class Sotto extends Sopra { public int b; public Sopra metodo2(int i) { Sopra c=new Sotto(); c.metodo1(i); Sotto w= new Sotto(); w=c; w.b=w.a; Sotto d=(Sopra) new Sopra(); return c;} {b=101;} Due errori: w e' dichiarata con tipo Sotto, mentre c con tipo Sopra d e' dichiarata con tipo Sotto, mentre il cast e’ verso Sopra