Cecchetti Luca - matr. 1602 002579 13/06/2001 Linguaggi Formali e Compilatori 3URJUDPPD]LRQHDG RJJHWWLLQ-DYD &RV·q -DYD Un linguaggio di programmazione orientato agli oggetti sviluppato dalla Sun Microsystem. Una tecnologia basata su macchina virtuale che interpreta le istruzioni di tale linguaggio appositamente compilato. &DUDWWHULVWLFKH GL -DYD Portabilità Linguaggio ad oggetti “puro” Gestione automatica della memoria (GC) Multithreading Sicurezza Semplicità Programmazione ad oggetti in Java 1 &ODVVH Modello generico (prototipo) per una famiglia di oggetti con caratteristiche simili, in pratica una struttura dati utilizzata per definire le caratteristiche e le funzionalità di un determinato tipo di oggetto. 2JJHWWR Insieme di dati (attributi) e funzioni (metodi) che ne definiscono lo stato ed il comportamento. Un oggetto è un’istanza di una classe, cioè una rappresentazione concreta di una classe. Figura 1 - Esempio di classe e varie istanze di essa Programmazione ad oggetti in Java 2 9DULDELOL Variabili istanza: definiscono gli attributi di un oggetto; tipi e nomi sono definiti nella classe, i valori impostati e modificati dai singoli oggetti. Esempio: int varIstanza; Variabili di classe: definite e memorizzate nella classe stessa, sono accessibili da ogni istanza e hanno un valore unico. Esempio: static int varDiClasse; 0HWRGL Metodi: funzioni definite all’interno di una classe, che agiscono sulle istanze di quest’ultima. Esempio: public void metodo(); Metodi di classe: funzioni di utilità generale definite all’interno di una classe, che si applicano alla classe stessa e non alle sue istanze. Esempio: public static void metodoDiClasse(); Programmazione ad oggetti in Java 3 (VHPSLR FODVVH public class Veicolo { private String marca, modello; private int immatricolazione; private int ruote; private boolean fermo; private static int contatore = 0; Veicolo(String ma, String mo, int i, int r) { this.marca = ma; this.modello = mo; this.immatricolazione = i; this.ruote = r; this.fermo = true; this.contatore++; } public boolean isFermo() { return this.fermo; } public String getInfo() { return marca + " " + modello + " (" + immatricolazione + ")"; } public static int numIstanze() { return contatore; } } Programmazione ad oggetti in Java 4 (UHGLWDULHWj n Meccanismo che permette di definire una sottoclasse di una classe già esistente; la nuova classe acquisisce tutti i metodi e le variabili della classe superiore (superclasse). L’ereditarietà permette di costruire una gerarchia di classi: al vertice della gerarchia di Java si trova la classe Object, dalla quale ereditano tutte le classi. Java prevede solo l’ereditarietà singola: ogni classe ha una sola superclasse. Object Veicolo VeicoloAPedali VeicoloAMotore Figura 2 – Esempio di gerarchia Programmazione ad oggetti in Java 5 (VHPSLR VRWWRFODVVH public class VeicoloAMotore extends Veicolo { private Motore motore; VeicoloAMotore(String ma, String mo, int i, int r, int cc, byte benz) { super(ma, mo, i, r); motore = new Motore(cc, benz); } public String getInfo() { return super.getInfo() + " - " + motore.getCC() + "cc"; } public boolean accendi() { ... } public boolean spegni() { ... } } Programmazione ad oggetti in Java 6 (UHGLWDULHWj o La pianificazione preliminare di una gerarchia per la struttura del codice porta i seguenti vantaggi: parti comuni a più classi riunite in una superclasse; modifica di una superclasse senza bisogno di ricompilare le sottoclassi. Una sottoclasse eredita tutte le variabili e i metodi della superclasse e delle classi che la precedono nella gerarchia. Le variabili istanza vengono create all’atto dell’istanziazione di una classe. Le definizioni dei metodi per un oggetto vengono scelte dinamicamente al momento della chiamata (dinamic binding). Classe Metodo Classe Classe Classe Classe Oggetto Oggetto Figura 3 – Dinamic binding Programmazione ad oggetti in Java 7 (UHGLWDULHWj p In una sottoclasse è possibile ridefinire i metodi ereditati dalla superclasse rispettando la dichiarazione originale (overriding). Con il binding dinamico verrà eseguito il primo metodo incontrato risalendo la gerarchia. Definizione Classe Metodo Ridefinizione Classe Classe Metodo Classe Classe Oggetto Oggetto Figura 4 – Dinamic binding Ridefinendo un metodo con diverso numero e/o tipo di parametri si ha overloading di metodi. Al momento della chiamata interviene il binding dinamico. Programmazione ad oggetti in Java 8 9DULDELOL Var. istanza: Var. di classe: Costanti: int x; static int y; static final int z = 33; 0HWRGL La segnatura di un metodo è definita dal nome e dalla lista dei parametri che accetta (numero e tipo). In una classe non possono esistere due metodi con la stessa segnatura, anche se restituiscono tipi di dato diversi. Esempio: class Coppia { float x, y; Coppia(float a, float b) { x=a; y=b; } float somma() { return x+y; } int somma() { return (int)(x+y); } } genererà un errore di compilazione. 3DVVDJJLR GHL SDUDPHWUL Di tipo primitivo, per valore. Di tipo oggetto, per riferimento. Programmazione ad oggetti in Java 9 0HWRGL FRVWUXWWRUL I metodi costruttori vengono eseguiti quando si crea un oggetto; devono avere lo stesso nome della classe. In caso di overloading, è possibile richiamare un costruttore all’interno di un altro utilizzando la parola chiave this. Esempio: this(arg1, arg2, ...); In caso di overriding, è possibile richiamare il costruttore della superclasse usando la parola chiave super. Esempio: super(arg1, arg2, ...); 0HWRGL FRQFOXVLYL I metodi conclusivi (finalizer) vengono eseguiti automaticamente prima della rimozione di un oggetto dalla memoria. Ogni classe eredita il metodo conclusivo dalla classe Object: protected void finalize() throws Thrownable { ... } Programmazione ad oggetti in Java 10 8WLOL]]R GHJOL RJJHWWL Le istanze di una classe si creano con la parola chiave new. Esempio: Veicolo x = new Veicolo("Fiat", "500", 1970, 4); Cosa fa new: alloca la memoria per l’oggetto inizializza le variabili istanza esegue il metodo costruttore L’accesso alle variabili e ai metodi avviene utilizzando espressioni in notazione puntata. Esempio: System.out.println(x.getInfo()); Le variabili che rappresentano oggetti in realtà sono dei riferimenti agli oggetti. Per verificare se due variabili fanno riferimento allo stesso oggetto si usano gli operatori di confronto “==” e “!=”. Per verificare se un oggetto è un’istanza di una classe particolare si usa l’operatore instanceof. Esempio: boolean b = (x instanceof Veicolo); // b=true Un’istanza di una classe A può essere convertita in un’istanza di una classe B solo se A è una sottoclasse di B oppure A è la superclasse di B (casting). NB: nel secondo caso non è sempre possibile. Programmazione ad oggetti in Java 11 0RGLILFDWRUL n Sono speciali parole chiave che modificano la definizione (e il comportamento) di una classe, un metodo o una variabile. Protezione private – metodi e varabili sono accessibili solo ad altri metodi della stessa classe. protected – metodi e varabili sono accessibili a tutte le classi dello stesso package e alle sottoclassi esterne. public – metodi e variabili sono accessibili a tutte le classi. package – metodi e variabili sono accessibili a tutte le classi dello stesso package. In genere conviene proteggere le variabili istanza con private e renderle accessibili con particolari metodi di accesso. Esempio: public class Cerchio { private int x, y, r; public int getRaggio() { return r; } public void setRaggio(int n) { r = n; draw(); } } Programmazione ad oggetti in Java 12 0RGLILFDWRUL o Variabili e metodi di classe – static Esempi: private static int contatore; public static int numIstanze() { ... } In genere per le variabili di classe vale lo stesso discorso fatto per le variabili istanza. Inoltre è preferibile riferirsi a variabili e metodi di classe usando il nome della classe. Esempio: x = Veicolo.numIstanze(); Finalizzazione – final Serve per bloccare l’implementazione o il valore di classi, metodi e variabili. public final class Auto { ... } public final void metodo { ... }; static final int piGreco = 3.1415; impedisce la creazione di sottoclassi; impedisce la ridefinizione del metodo nelle sottoclassi; dichiarazione di una costante. Programmazione ad oggetti in Java 13 0RGLILFDWRUL p Classi e metodi astratti – abstract Le classi astratte hanno lo scopo di fornire informazioni comuni per le sottoclassi, quindi non sono istanziabili. Possono contenere metodi astratti, cioè metodi con segnatura ma senza implementazione, che deve essere fornita dalle sottoclassi. Esempio: public abstract class Figura { protected int colore; public abstract void draw(); } public class Cerchio extends Figura { private int x, y, r; public void draw() { ... } } public class Rettangolo extends Figura { private int w, h; public void draw() { ... } } Programmazione ad oggetti in Java 14 3DFNDJH I package sono uno strumento per raggruppare le classi. Utilità: Organizzazione delle classi in una struttura a file-system. Riduzione dei conflitti tra i nomi. Maggiore protezione delle classi. Semplice identificazione di gruppi di classi. La libreria di classi di Java è organizzata in package; eccone alcuni: java.applet java.awt java.awt.event java.awt.image java.io java.lang java.math java.net java.security java.util java.util.zip Programmazione ad oggetti in Java 15 8WLOL]]R GHL SDFNDJH Per usare una classe di un determinato package ci sono tre modi: Se la classe è in java.lang essa è disponibile per default. Per altri package si può usare il nome completo. Esempio: java.util.Date d = java.util.Date("..."); Per classi utilizzate frequentemente è possibile importare l’intero package e fare riferimento ad esse usando solo il nome. Esempio: import java.util.*; // import java.util.Date; ... Date d = Date("..."); &UHD]LRQH GL SDFNDJH Scelta del nome Creazione della struttura a directory Aggiunta delle classi Esempio: package prova; class ClasseNascosta { ... } public class ClasseVisibile { ... } NB: solo le classi di tipo public possono essere importate dall’esterno. Programmazione ad oggetti in Java 16 ,QWHUIDFFH n Le interfacce forniscono modelli di comportamento implementabili da altre classi e vengono introdotte per superare la limitazione dell’ereditarietà singola. Ogni volta che due classi possono avere dei comportamenti simili ma non sono in relazione gerarchica fra loro, è possibile definire un’interfaccia che contiene le definizioni dei metodi comuni e specificare opportunamente che le classi interessate implementano tale interfaccia. Frutta Mela Arancia Banana Limone Figura 5 – Classe Frutta con sottoclassi Nell’esempio le classi Arancia e Limone potrebbero avere un metodo spremi(), ma non avrebbe senso definirlo nella superclasse Frutta. Si può allora creare un’interfaccia Spremibile in cui è definito il metodo comune alle due classi ed implementarlo nelle classi stesse. Programmazione ad oggetti in Java 17 ,QWHUIDFFH o public interface Spremibile { void spremi(); // public e abstract sono impliciti } public abstract class Frutta { protected String colore, stagione; public boolean matura(); } public class Arancia extends Frutta implements Spremibile { public void spremi() { if( matura() ) ... } } Note: Una classe può implementare più di un’interfaccia. Le interfacce possono essere organizzate in una gerarchia, in questo caso si può avere anche ereditarietà multipla. Nelle interfacce si possono definire solo metodi astratti (pubblici) e costanti. Le interfacce si possono inserire all’interno di package. Programmazione ad oggetti in Java 18 (FFH]LRQL Le eccezioni sono eventi che possono provocare la terminazione di un programma o di un applet. Gestendole in modo opportuno è possibile controllare gli errori ed eventualmente risolverli. Le eccezioni sono oggetti, istanze di classi che derivano dalla classe Throwable. Throwable Error Exception RuntimeException IOException Figura 6 – Gerarchia delle classi di eccezioni &DWWXUD GHOOH HFFH]LRQL Il codice che potrebbe generare eccezioni viene eseguito all’interno di un blocco try, poi si tenta di scoprire eventuali eccezioni con uno o più blocchi catch; infine con la clausola finally (opzionale) è possibile indicare quali azioni compiere in ogni caso. Il metodo che contiene del codice di questo tipo deve essere definito in modo particolare. Programmazione ad oggetti in Java 19 (VHPSLR JHVWLRQH HFFH]LRQL import java.io.*; public class testEccezione { InputFileStream f; public void apriFile(String fn) throws FileNotFoundException { try { f = new InputFileStream(fn); } catch(FileNotFoundException e) { System.out.println("Eccezione catturata"); throw e; } } public static void main(String arg[]) { testEccezione t = new testEccezione(); try { t.apriFile("nonesiste.txt"); } catch(FileNotFoundException e) { System.out.println("Ricatturata da main()"); } } } Programmazione ad oggetti in Java 20