Package, Interfacce, Ereditarietà Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Slides:



Advertisements
Presentazioni simili
Programmazione ad oggetti
Advertisements

Classi ed Oggetti in JAVA
© 2007 SEI-Società Editrice Internazionale, Apogeo Unit à B2 Gli oggetti: concetti avanzati.
Costruttori e Distruttori
Recupero debito quarto anno Primo incontro
Recupero debito quarto anno Secondo incontro
Informatica Recupero debito quarto anno Terzo incontro.
Informatica 2 Lezione 4 Corso di laurea in matematica Informatica 2 Dott. Ing. Leonardo Vito Corso di laurea matematica indirizzo matematica per le applicazioni.
Java: programmazione concorrente con condivisione di memoria
Differenze nei vari linguaggi di Elisa Trifirò e Barbara Tacchino
Classi ed Oggetti in Java (Cenni). Richiami Ruolo delle Classi in Java Oggetti.
Le gerarchie di tipi.
Liste Ordinate 3 Maggio Ultima Lezione Abbiamo visto i tipi di dato astratti IntList e StringList Realizzano liste di interi e di stringhe Realizzati.
LIP: 1 Marzo 2005 Classe Object e Vettori. Partiamo da Lesercizio dellultima esercitazione realizzato tramite array Vedremo come si puo fare in modo piu.
Fondamenti di Informatica
Interfacce. Interfacce come strumento di progetto Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce e riuso di codice.
Eccezioni Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – – SIENA Uff
Programma Dott. Ing. Leonardo Rigutini
Applet Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – – SIENA Uff
Tipi di dato e controllo del flusso Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – – SIENA.
1 Programmazione ad oggetti in Java E.Mumolo, DEEI
1 Corso di Laurea in Biotecnologie Informatica (Programmazione) Introduzione a JAVA Anno Accademico 2009/2010.
Introduzione al linguaggio Java
1 Lezione XIII Lu 17-Nov-2005 Programmare le classi.
Derivazione tra classi
Overriding.
Oggetti e dati primitivi
Gerarchia di classi Java
1 Le gerarchie di tipi. 2 Supertipi e sottotipi 4 un supertipo –class –interface 4 può avere più sottotipi –un sottotipo extends il supertipo ( class.
Lab. Calc. 2005/06 Ereditarietà. Lab. Calc. 2005/06 Scopo di questa lezione: Imparare a creare nuove classi ereditando da classi già esistenti. Capire.
Programmazione con Interfacce
Le classi Definizione di classe Attributi e metodi di una classe Costruttori e distruttori Private e public Funzioni friend Il puntatore this.
Java base IV: Java e la programmazione O.O.
IL CONCETTO DI PACKAGE Una applicazione è spesso composta di molte classi (eventualmente correlate) Un package è un gruppo di classi che costi- tuiscono.
IL TEMA DELLA RIUSABILITÀ Si vuole riusare tutto ciò che può essere riusato (componenti, codice, astrazioni) Non è utile né opportuno modificare codice.
IL TEMA DELLA RIUSABILITÀ Si vuole riusare tutto ciò che può essere riusato (componenti, codice, astrazioni) Non è utile né opportuno modificare codice.
Programmazione in Java (8)
AlgoLab - Ereditarieta' Ereditarietà e polimorfismo in Java Laboratorio di Algoritmi 02/03 Prof. Ugo de Liguoro.
Ereditarietà e Polimorfismo
Enumerazioni e Classi 1. Enumerazioni Permettono di definire nuovi tipi che consistono in un insieme di valori costanti (ognuno con un nome) – Migliorano.
1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.
Fondamenti di Programmazione Prof.ssa Elisa Tiezzi
ISTITUTO STATALE DI ISTRUZIONE SUPERIORE F. ENRIQUES CORSO JAVA – PROVA FINALE DEL 21 MAGGIO 2007 NOME: COGNOME: ________________________________________________________________________________.
ISTITUTO STATALE DI ISTRUZIONE SUPERIORE F. ENRIQUES CORSO JAVA – PROVA INTERMEDIA DEL 12 MARZO 2007 NOME: COGNOME: ________________________________________________________________________________.
JAVA Per iniziare. Verificare installazione javac –version java –version Cercare i files e sistemare eventualmente il path.
30/11/2004Laboratorio di Programmazione - Luca Tesei1 Interfacce e Polimorfismo.
Ereditarieta’. Contenuti Introduciamo un meccanismo fondamentale di Java: l’ereditarieta’ Permette di estendere classi gia’ definite (ovvero di definire.
1 Osservazioni Generali Struttura di programma Gerarchia di classi: overloading, overriding, e dispatching Analisi ed esecuzione Modificabilità e condivisione.
Fondamenti di Informatica II Ingegneria Informatica Prof. M.T. PAZIENZA a.a – 3° ciclo.
Fondamenti di Informatica II Ingegneria Informatica (A-I) Prof. M.T. PAZIENZA a.a – 3° ciclo.
Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 7 Tipi di dato e strutture dati Specifica e realizzazione di strutture informative come classi.
Fondamenti di Informatica 2 Ingegneria Informatica Docente: Giovanni Macchia a.a
1 Eccezioni in Java. 2 Ricordiamo che 4 una procedura può terminare –normalmente, ritornando un risultato –in modo eccezionale ci possono essere diverse.
Gestione dei thread in Java
Fondamenti di informatica Oggetti e Java Luca Cabibbo Luca Cabibbo – Fondamenti di informatica: Oggetti e Java Copyright © 2004 – The McGraw-Hill Companies.
Programmazione in Java. Classi I programmi in Java consistono di classi. Le classi consentono di definire: collezioni di procedure (metodi statici) tipi.
Cose nuove di Java (prima a chiacchiera, poi formalmente)
Ereditarieta’. Contenuti Introduciamo un meccanismo fondamentale di Java: l’ereditarieta’ Permette di estendere classi gia’ definite (ovvero di definire.
Ereditarieta’. Contenuti Introduciamo un meccanismo fondamentale di Java: l’ereditarieta’ Permette di estendere classi gia’ definite (ovvero di definire.
Progettare una classe 21 Febbraio La classe BankAccount Vogliamo realizzare una classe i cui oggetti sono dei semplici conti bancari. * Identifichiamo.
Esercitazione del 9 marzo 2007 Ereditarieta’. Richiami Definire sottoclassi (ereditarieta’) Overriding Specificatori di accesso (private, protected) Principio.
LIP: 4 Maggio 2007 Interfacce. Cos’e’ una Interfaccia una interfaccia e’ un particolare tipo di classe contiene solo la specifica non ha implementazione.
Corso di Algoritmi e Strutture Dati con Laboratorio Richiami di Java – parte II.
Corso di Algoritmi e Strutture Dati con Laboratorio A.A. 2015/16 Oltre le classi.
La programmazione ad oggetti
28/12/2001package 1 Package Pacchetti e interfacce.
Introduzione all’Ereditarietà Pietro Palladino. Richiami UML Classe: descrizione di un insieme di oggetti software con caratteristiche simili Definisce.
Introduzione alle Classi e agli Oggetti in Java 1.
Transcript della presentazione:

Package, Interfacce, Ereditarietà Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – – SIENA Uff

Package

I package Un programma JAVA è costituito da una raccolta di classi. Finora i nostri programmi erano composti da un piccolo numero di classi Quando queste tuttavia aumentano di numero, limitarsi a distribuire le classi su più file non basta ed occorre un meccanismo per organizzare le collezioni di classi in modo chiaro e semplice In JAVA questo meccanismo è fornito dai pacchetti: un pacchetto (package) è costituito da una serie di clssi correlate La libreria JDK è costituita da centinaia di classi organizzate in dozzine di pacchetti: java.lang, java.awt, java.io, ecc…

Definire il package Per inserire le classi in un pacchetto si usa la seguente sintassi allinizio del file: package NOME_PACCHETTO; Il nome del pacchetto può essere costituito da una serie di identificatori, separati da punti: Lidea è quella di organizzare i package in maniera gerarchica e quindi dare la possibilità di creare un albero di pacchetti Ogni punto individua un ramo dellalbero

Importare pacchetti Se vogliamo utilizzare una classe di un pacchetto è necessario specificare al compilatore di quale pacchetto abbiamo bisogno E possibile dereferenziare direttamente la classe utilizzando il percorso completo della classe in fase di dichiarazione di una variabile oggetto: Questo sistema è evidentemente molto scomodo, quindi in alternativa è possibile importare allinizio della definizione della classe i pacchetti che poi verranno utilizzati nel codice tramite la parola import: java.awt.Rectangle R= new java.awt.Rectangle(5,10,20,30) import java.awt.Rectangle; … Rectangle R= new Rectangle(5,10,20,30)

Importare package Quando di un package sono utilizzate molte classi, è possibile collassare le molte righe relative a quel package in una riga In questo modo viene specificato di importare tutte le classi presenti nel package Nel caso si utilizzi package omonimi o classi omonime in package diversi, è necessario utilizzare comunque la notazione estesa per risolvere leventuale ambiguità import java.awt.*; import java.awt.Rectangle; import java.awt.Color;

Come vengono organizzate le classi I package hanno una corrispondenza fisica sul progetto che si sta sviluppando: Ovvero se una classe fa parte di un package, allora deve risiedere in una cartella il cui percorso di directory coincide con la gerarchia del package Es package prova.bankaccount; La classe deve essere salvata in [CLASSPATH]/prova/bankaccount/BankAccount.class

Come vengono organizzate le classi Notare come la root deve essere una directory nel CLASSPATH del JCompiler e della JVM Se vogliamo che la classe BankAccount o tutto il package bankaccount.prova.* siano visibili in una classe terza, è necessario inserire la directory da cui classes.bankaccount.* nasce: C:\Programmi\JBuilder2005\jdk1.4\bin\javaw -classpath D:\Documenti\Activities\Teaching\LinguaggiProgrammazione - storing2005\Examples\04.Package\01.BankAccount-Package\classes; Directory root per i package prova.* e prova.bankaccount.*

Pacchetti compressi Usualmente il pacchetto viene fornito in formato compresso (jar): Allinterno del file.jar vengono memorizzate le classi del pacchetto in una struttura a directory che rispecchia i package di ogni classe Nella creazione del jar è possibile specificare se includere anche le dipendenze, ovvero tutti quelle classi (con i relativi package) che sono utilizzate nel pacchetto che stiamo costruendo Inoltre è possibile inserire nel file.jar anche la documentazione, in modo da avere un pacchetto completo memorizzato in un singolo file e compresso

…\04.Package\01.BankAccount-Package>java –cp BankAccount.jar prova.TestBankAccount Pacchetti compressi Lutilizzo dei file jar segue quello deli pacchetti normali: Nel CLASSPATH è possibile specificare come path di ricerca classi anche i files.jar in cui sono memorizzati i package Il JCompiler e la JVM entrano allinterno dei file jar per utilizzare tutte le classi necessarie …\04.Package\01.BankAccount-Package>java TestBankAccount Exception in thread "main" java.lang.NoClassDefFoundError: TestBankAccount File jar per la classe prova.TestBankAccount e per la classe prova.bankaccount.BankAccount Chiamata della classe TestBankAccount specificando il package

Interfacce e polimorfismo

Riutilizzo Supponiamo di avere una classe DataSet che calcola alcune statistiche di un insieme di valori in ingresso (media, massimo, varianza ecc…). Vorremmo una classe che calcoli le stesse informazioni su oggetti BankAccount (diversi dai semplici numeri). La cosa che dobbiamo fare è modificare la classe Dataset aggiungendo metodi che ricevono come parametro oggetti BankAccount In questo modo però se vogliamo estendere le funzionalità della classe DataSet ad altre classi (Coin per esempio) rimane necessario ogni volta aggiungere metodi per la classe desiderata

Riutilizzo public class DataSet { public void add(int n) { sum+=n; cc++; } public double avg() { return sum/cc; } public class DataSet { private int sum; private int cc=0; public void add(BankAccount B) { sum+=B.getBalance(); cc++; } public void add(Coin C) { sum+=C.getValue(); cc++; } public double avg() { return sum/cc; }

Riutilizzo Possiamo notare però che il meccanismo per lanalisi dei dati è il solito in tutti i casi: viene letto il valore delloggetto passato e viene calcolata linformazione richiesta Se tutte le classi che noi vogliamo passare alle funzioni di DataSet potessero accordarsi su un unico metodo getValue() che ritorna il valore su cui la classe DataSet calcola le statistiche, potremmo definire una sola funzione add()

Riutilizzo Ma che tipo di oggetto passiamo come parametro per add() ? Definiamo una classe fittizia Measurable che descrive solamente linterfaccia comune e poi specifichiamo le diverse classi che implementano linterfaccia public interface Measurable { public double getValue(); } public class DataSet { public void add(Measurable x) { sum+=x.getValue(); cc++; } public double avg() { return sum/cc; }

Riutilizzo Le classi che dovranno essere passate come parametri di add(Measurable x) dovranno essere specificate come implementazioni della classe Measurable e dovranno implementare il metodo specificato nellinterfaccia: public class BankAccount implements Measurable { public double getValue() { return balance; } public class Coin implements Measurable { public double getValue() { return value; }

Interfaccia I metodi di una interfaccia non sono dichiarati public perché lo sono per impostazione predefinita. Tuttavia, i metodi di una classe non sono pubblici se ciò non viene specificato: Quindi nell implementazione di una interfaccia è necessario specificare i metodi come public La classe Measurable, è una descrizione di più alto livello delle classi BankAccount e Coin. E possibile quindi utilizzare una variabile oggetto di tipo Measurable per memorizzare un oggetto di tipo BankAccount o Coin Measurable x=new Coin();

Operatore instanceof Loperazione inversa, invece, non è immediata come la precedente: Se siamo sicuri che un oggetti di tipo Measurable sia di tipo Coin possiamo forzare la conversione tramite un cast Nel caso però in cui la forzatura non sia valida, ossia a run-time loggetto forzato non è di tipo Coin, viene ritornato errore Per verificare a run-time la corretta appartenenza ad una classe di un oggetto è possibile utilizzare loperatore instanceof: Measurable x= …; Coin y=(Coin)x; Measurable x= …; Coin y; If (x instanceof Coin) { y=(Coin)x; }

Interfacce Le interfacce non possono avere variabili, ma è possibile dichiarare constanti che verranno ereditate da tutte le classi che implementano linterfaccia: Quando vengono dichiarate le costanti in una interfaccia dovrebbero essere omesse le parole chiave public, static e final poiché tutte le variabili in una interfaccia sono definite automaticamente public static final public interface Move{ int NORTH=0; int EAST=3; int SOUTH=6; int WEST=9; }

Polimorfismo La riga di codice è molto utilizzata in pratica e permette di avere la variabile x disponibile per memorizzare oggetti di classi diverse: Occorre ricordare però che in realtà non esiste alcun oggetto di tipo Measurable. Il tipo delloggetto sarà sempre una classe che implementa linterfaccia Measurable x; x=new BankAccount(); x=new Coin();

Polimorfismo Pensiamo adesso a cosa accade quando viene chiamata una funzione dellinterfaccia: la JVM risolve il tipo delloggetto su cui è chiamato il metodo dinterfaccia ed invoca quello relativo alla classe corretta Ciò significa che linvocazione di un metodo dinterfaccia può chiamare metodi diversi: Il principio secondo cui il tipo delloggetto determinato a run-time determina il metodo da chiamare è detto polimorfismo In realtà in JAVA tutti i metodi sono polimorfi, poiché la scelta del metodo giusto da eseguire può dipendere dalla valutazione delle classi passate come parametro: overloading

Inner Class

Le Inner class sono classi definite allinterno di altre classi. class Homer { class Son { public void Speak() { System.out.println(Son: Eat my socks!"); } Son Bart = new Son(); public void Speak() { System.out.println("Homer: DOH!"); Bart.Speak(); }

Inner Class Le Inner class non possono essere istanziate direttamente con new da classi esterne: Un modo per rendere visibile la classe è creare un metodo che ritorni una istanza della Inner Class: Homer.son Bart = new Homer.Son(); ERRORE class Homer { … public Son CreateSon() { return new Son(); } public static void main(String[] args) { Homer Homer1 = new Homer(); Homer.Son Bart = Homer1.CreateSon(); } OK

Inner Class Le Inner class che implementano interfacce pubbliche possono essere visibili allesterno pur avendo limplementazione nascosta allinterno della classe contenitore interface Simpson { public void Speak(); } class Homer { pricate class Son implements Simpson { public void Speak() { System.out.println(Son: Eat my socks!"); } : }

Inner Class definite nei metodi Le Inner class possono essere definite anche nei metodi, nascondendole del tutto al resto del programma È possibile utilizzare queste classi allesterno solo se posseggono una interfaccia pubblica o una classe base class Homer { public void Speak() { class Son { System.out.println(Son: Eat my socks!"); } : }

Inner Class anonime È possibile costruire classi innestate senza specificare il tipo, ma solo specificando linterfaccia che implementano interface Point { public void setXY(int x, int y) public int getX(); public int getY(); } public class Prova { static public Point getPoint(final int x, final int y) { return new Point() { private int X, Y; {X = x; Y = y; } public void setXY(int x, int y) {X = x; Y = y;} public int getX() { return X; } public int getY() { return Y; } } public static void main(String[] args) { Point p = getPoint(0, 0); System.out.println(P(+p.getX()+, +p.getY()+)); } Inner Class anonima che implementa linterfaccia Point

Ereditarietà

Organizzazione gerarchica Abbiamo visto che i package forniscono una struttura gerarchica per lorganizzazione delle classi Una organizzazione gerarchica può esistere però anche tra le classi: una classe può essere un tipo particolare di unaltra classe più generica: Veicolo Auto Ferrari È possibile definire una struttura tra classe in cui da una classe generale vengono derivate classi sempre più specifiche che ereditano le proprietà ed i metodi delle classi genitore

Eredità Come detto un problema può essere descritto in maniera più chiara se decomposto concettualmente in classi Molte volte può essere necessario individuare classi di classi: in molte situazioni infatti è possibile individuare oggetti generali da cui discendono una serie di classi del tipo di In tale immaginario, le classi derivate ereditano lo stato delle classi genitore, aggiungendo funzionalità proprie della classe specifica:

Ereditarietà Se pensiamo ad un veicolo, esso avrà delle funzioni (muovi, frena, gira ecc…) e delle proprietà (peso, lunghezza, larghezza ecc…) Da una classe di oggetti veicolo possono poi essere derivati altri tipi di oggetti: bicicletta, Autoveicolo, Motoveicolo ognuno con delle funzionalità proprie: ad esempio la funzione accendi() non dovrebbe appartenere alla classe bicicletta Inoltre la classe autoveicolo potrebbe a sua volta essere suddivisa in base al tipo di autoveicolo: Auto, camion, van, ecc… ognuna con proprietà e funzioni proprie e diverse dallaltro

Ereditarietà Veicolo AutoveicoloMotoveicolo Bicicletta AutomobileAutocarro UtilitariaBerlina Jeep

Ereditarietà In Java è possibile dichiarare una classe come figlia di unaltra classe tramite la parola extends La classe genitore viene riferita come superclasse, mentre la classe più specifica (figlia) viene chiamata sottoclasse Nei diagrammi, lereditarietà si indica con una freccia a vuoto diretta dal figlio verso il padre public class Auto extends Veicolo { } Veicolo Auto

Eredità o interfaccia ? A questo punto potremmo chiederci cosa ci sia di diverso tra lereditarietà e limplementazione di una interfaccia? Uninterfaccia non è una classe, non ha uno stato né un comportamento: indica solamente quali metodi sono da implementare. Una superclasse ha uno stato ed un comportamaento e questi vengono ereditati dalla classe derivata. Lereditarietà realizza il concetto di riutilizzo del codice: grazie allereditarietà, infatti, non siamo costretti a rifare il lavoro di progettazione della classe e di implementazione delle funzioni più generali

Ereditare variabili e metodi Quando definiamo una classe come estensione di una superclasse, ereditiamo tutte le variabili e le funzioni della classe genitore ed in più possiamo aggiungere nuove variabili o funzioni Cosa succede se ridefiniamo un metodo che già esiste nella superclasse? Il metodo viene sovrascritto (override) ovvero il metodo della superclasse è sostituito dalla nuova implementazione del metodo nella sottoclasse. Ogni chiamata a quel metodo da oggetti della sottoclasse, viene risolta con la nuova implementazione

Ereditare variabili e metodi Così come è possibile ridefinire le funzioni, è possibile ridefinire anche le variabili membro, mettendo in ombra così le variabili della superclasse omonime: in questo caso però, nella sottoclasse esiste comunque una istanza della variabile della superclasse In entrambi i casi è sempre possibile fare riferimento ad una variabile o un metodo della classe genitore tramite lindicatore di oggetto super: … super.drive(); … int y = super.carburante; Chiama esplicitamente la funzione drive() della classe genitore Legge il valore della variabile membro carburante della classe genitore

Costruttore Tramite la parola super, è possibile fare riferimento anche al costruttore della superclasse: class Quadrato extends Rettangolo { public Quadrato(float lung){ super(lung,lung); } public float diag(){ return Math.sqrt(2) * l; }.... Quadrato q1=new Quadrato(2); System.out.println(q1.area()); class Rettangolo { float h, l; public Rettangolo(float alt, float lung){ h=alt; l=lung; } public float diag(){ return Math.sqrt((h*h)+(l*l)); } override costruttore super-class

Visibilità Lereditarietà implica alcuni problemi di visibilità dei metodi e delle variabili Che diritti può avere una classe derivata su un metodo o una variabile membro della superclasse che è stata definita privata? È possibile definire variabili private che siano private ma utilizzabili per le classi derivate? Sono state definite le seguenti regole tra classi e sottoclassi: La visibilità di una variabile o di un metodo di una superclasse è specificata da specificatori di accesso

Specificatori di accesso Public – rende visibile la variabile o il metodo a tutte le classi Private – nasconde la variabile o il metodo a tutte le classi, comprese le classi derivate Protected – nasconde le variabili ed i metodi a tutte le classi tranne quelle nello stesso package Nessun specificatore – utilizza Protected come visibilità di default

Visibilità

Upcasting È la proprietà più importante dellereditarietà Il concetto è molto semplice: tutti i metodi che hanno una classe come parametro accettano anche tutti le classi derivate Il termine upcasting deriva dalla direzione con cui ci si muove sugli alberi di ereditarietà: Metodi Stato Metodi Stato Veicolo Auto

Upcasting public class Concessionario { protected Veicolo[] parcheggio; // costruttore: specifica la dimensione del parcheggio public Concessionario(int dim) { parcheggio = new Veicolo[dim]; } // mette un oggetto nel parcheggio senza controllare lo spazio public void add (Veicolo v) { parcheggio[parcheggio.length]=v; } Inserimento di un oggetto Veicolo: può essere un oggetto Auto, Autocarro, ecc… upcast

Downcasting Anche qui il concetto è semplice: se siamo sicuri che un handle, pur essendo di una classe, si riferisca ad un oggetto discendente, allora è possibile effettuare la conversione La conversione è forzata: cast esplicito // preleva un veicolo dal parcheggio: se è un oggetto Auto, // lo restituisce come oggetto Auto, altrimenti ritorna null public Auto getAuto(int x) { if (parcheggio[x] instanceof Auto) return (Auto) parcheggio[x]; return null; } downcast

RTTI (Run-Time Type Identification) Per risolvere un riferimento ad una superclasse si può utilizzare la risoluzione a run-time del tipo di oggetto Avevamo già visto nel caso di interface come risolvere a run-time il tipo di oggetto: instanceof LRTTI (Run-Time Type Identification) è il sistema che permette di capire a che classe appartiene un oggetto.

Downcasting public class Concessionario { protected Veicolo[ ] parcheggio; // costruttore: specifica la dimensione del parcheggio public Concessionario(int dim) { parcheggio = new Veicolo[dim]; } // mette un oggetto nel parcheggio senza controllare lo spazio public void add (Veicolo v) { parcheggio[parcheggio.length]=v; } // preleva un veicolo dal parcheggio: se è un oggetto Auto, // lo restituisce come oggetto Auto, altrimenti ritorna null public Auto getAuto(int x) { if (parcheggio[x] instanceof Auto) return (Auto) parcheggio[x]; return null; } Inserimento di un oggetto Veicolo: può essere un oggetto Auto, Autocarro, ecc… upcast Prelievo di un Oggetto Auto: cast da Veicolo ad Auto downcast

Lo specificatore final Avevamo visto che final era utilizzato allinterno di una classe per definire una costante: Una variabile inizializzata in fase di dichiarazione e non più modificabile È possibile utilizzare final anche per i metodi: in tal caso il metodo non può più essere sovrascritto in una classe derivata

Lo specificatore abstract Il JAVA permette di definire classi i cui metodi non hanno implementazione, queste classi si dicono astratte (abstract): Una classe astratta non può essere istanziata ma solamente estesa da classi derivate abstract class Shape { }

Lo specificatore abstract Una classe astratta può avere dei metodi astratti che quindi non devono essere implementati: Se una classe ha almeno un metodo astratto, deve essere dichiarata abstract abstract class Poligono { … abstract double getArea(); … }

Lo specificatore abstract I metodi astratti però devono essere implementati obbligatoriamente nelle classi derivate, a meno che anchesse siano dichiarate abstract abstract class Poligono { … abstract double getArea(); double nLati() { return n; } class Quadrato extends Poligono { … double getArea() { return l*l; } … }

Classi astratte I vantaggi nella definizione di classi abstract sono: definire una classe abstract significa definire una interfaccia comune a tutte le classi derivate una classe abstract non può essere istanziata: se ciò viene fatto il compilatore produce un errore. Questo permette al progettista della classe di costringere lutente a definire il comportamento dei metodi astratti

abstract ed interface Ma cosa distingue una classe astratta da un interfaccia? Nelle classi astratte è possibile definire proprietà utilizzando tutti gli specificatori di visibilità (public, private, ecc …), mentre nelle interfacce questo non è possibile: in questo caso infatti le variabili divengono automaticamente STATIC and FINAL Nella interface il concetto di implementazione è assolutamente inesistente. In pratica si stabilisce un protocollo di accesso, che poi verrà utilizzato da tutte le classi che utilizzano la medesima interfaccia L interface permette lereditarietà multipla

La classe Object Lereditarietà in Java prevede una classe ROOT da cui discende qualsiasi altra classe: la classe Object Ogni classe, che rappresenti qualsiasi entità, è sicuramente una derivazione della classe Object e quindi mette a disposizione i metodi di tale superclasse: protected Object clone() – copia Boolean equals(Object obj) – uguaglianza protected void finalize() – dealloca loggetto (Garbage Collector) Class getClass() – ritorna il tipo delloggetto a run-time int hashCode() – ritorna un hash per loggetto Dovuti al fatto che JAVA lavora con i riferimenti Risoluzione del tipo a run-time

La classe Object void notify() – riprende un thread fermo su questo oggetto void notifyAll() – sveglia tutti i thread fermi su questo oggetto String toString() – ritorna una rappresentazione in stringa delloggetto void wait() – ferma loggetto fino a che non viene chiamato il notify() o notifyAll() void wait(long timeout) – come sopra però con un timeout massimo void wait(long timeout, int nanos) – come sopra però permette di specificare il timeout in nanosecondi Ritorna una versione stampabile delloggetto

Garbage Collector

Quanto vivono gli oggetti? Il programmatore si occupa di costruire gli oggetti, ma non di distruggerli In JAVA la deallocazione degli oggetti è gestita automaticamente: quando un oggetto non è più utilizzato, la memoria utilizzata viene liberata automaticamente Lentità che si occupa di liberare memoria non più utile è il Garbage Collector public void xxx(){ Float W = new Float(0.5); } Lhandle W scompare, ma non loggetto associato!

Il Garbage Collector Il garbage collector è avviato automaticamente dalla JVM, ma è possibile forzare la chiamata al Garbage Collector tramite una funzione ereditata da tutte le classe dalla classe Object: È possibile capire se un oggetto è ancora referenziato (vivo) utilizzando due possibili tecniche: Conteggio Ricostruzione System.gc();

Conteggio Questa tecnica prevede di contare i riferimenti agli oggetti. Lo svantaggio è che molte volte gli oggetti si auto-referenziano: B C A da variabile non utilizzato

Ricostruzione Unaltra tecnica è quella di seguire a ritroso i riferimenti fino ad una variabile static oppure presente nello stack ed ancora attiva: A: B: C: C A non utilizzato B C: Memoria B: D Memoria AC B D

Strategie di GC Ma cosa fare quando vengono trovati gli oggetti non più utilizzati? Stop-and-Copy: una volta trovati gli oggetti da rimuovere, vengono copiati in un altro heap gli oggetti ancora referenziati, e modificati tutti i riferimenti a loro collegati. Lheap originario è sostituito dal nuovo heap. Mark-and-Sweep: una volta trovati gli oggetti da rimuovere, questi vengono eliminati senza copiare quelli ancora referenziati. In seguito lheap può essere riorganizzato spostando solo alcuni oggetti ancora vivi, più piccoli degli spazi rilasciati.

Adaptive Garbace Collection La tendenza attuale è quella di utilizzare entrambe le tecniche (Adaptive Garbace Collection), ma in momenti diversi: la tecnica Stop-and-Copy viene utilizzata solo quando lheap è troppo frammentato, e quindi è necessaria una riorganizzazione la tecnica Mark-and-Sweep è più veloce, ma lheap viene frammentato