INNER CLASS Una Inner class è una classe la cui dichiarazione si trova all’ interno di un’ altra classe (La classe ospitante è detta top level): class.

Slides:



Advertisements
Presentazioni simili
Programmazione ad oggetti
Advertisements

Funzioni e procedure Ogni linguaggio di programmazione ad alto livello mette a disposizione del programmatore questi strumenti, ed il C non è da meno!
Tipi di dato astratti Lista, Pila, Coda, Albero.
Informatica Recupero debito quarto anno Terzo incontro.
Differenze nei vari linguaggi di Elisa Trifirò e Barbara Tacchino
1 Astrazioni sui dati : Specifica ed Implementazione di Tipi di Dato Astratti in Java.
1 Semantica Operazionale di un frammento di Java: lo stato.
Classi ed Oggetti in Java (Cenni). Richiami Ruolo delle Classi in Java Oggetti.
Liste di Interi Esercitazione. Liste Concatenate Tipo di dato utile per memorizzare sequenze di elementi di dimensioni variabile Definizione tipicamente.
Le gerarchie di tipi.
1 Informatica Generale Susanna Pelagatti Ricevimento: Mercoledì ore presso Dipartimento di Informatica, Via Buonarroti,
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
Indirizzi delle variabili A ogni variabile sono associati tre concetti fondamentali: il valore memorizzato; il tipo dati di appartenenza; lindirizzo. Il.
Caratteri e stringhe di caratteri
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE Puntatori Marco D. Santambrogio – Ver. aggiornata al 21 Marzo 2013.
1 Programmazione ad oggetti in Java E.Mumolo, DEEI
1 Corso di Laurea in Biotecnologie Informatica (Programmazione) Introduzione a JAVA Anno Accademico 2009/2010.
1 Corso di Informatica (Programmazione) Lezione 13 (21 novembre 2008) Programmazione in Java: stringhe e array.
Corso di Laurea in Biotecnologie Informatica (Programmazione)
1 Lezione XIII Lu 17-Nov-2005 Programmare le classi.
Derivazione tra classi
Lezione 4: Costrutti Condizionali Prof. Raffaele Montella.
Istruzioni di selezione in Java Programmazione Corso di laurea in Informatica.
Approfondimento delle classi
Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,
Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,
Le classi Definizione di classe Attributi e metodi di una classe Costruttori e distruttori Private e public Funzioni friend Il puntatore this.
Le funzioni.
LA DOCUMENTAZIONE È noto che un buon programma dovrebbe essere ben documentato.. ma lesperienza insegna che quasi mai ciò viene fatto! –non cè tempo, ci.
IL CONCETTO DI PACKAGE Una applicazione è spesso composta di molte classi (eventualmente correlate) Un package è un gruppo di classi che costi- tuiscono.
FUNZIONI... Una funzione permette di dare un nome a una espressione rendendola parametrica float f(){ return * sin(0.75); } float f1(int x) { return.
I Metodi in Java Il termine "metodo" è sinonimo di "azione". Quindi, affinché un programma esegua qualche istruzione, deve contenere metodi.
1 Astrazioni sui dati : Ragionare sui Tipi di Dato Astratti dispense prof. G. Levi.
Enumerazioni e Classi 1. Enumerazioni Permettono di definire nuovi tipi che consistono in un insieme di valori costanti (ognuno con un nome) – Migliorano.
BIOINFO3 - Lezione 331 SUBROUTINE IN PERL Una subroutine (funzione, metodo, procedura o sottoprogramma), e` una prozione di codice all`interno di un programma.
Fopndamenti di programmazione. 2 La classe String Una stringa è una sequenza di caratteri La classe String è utilizzata per memorizzare caratteri La classe.
Corso JAVA Lezione n° 11 Istituto Statale di Istruzione Superiore “F. Enriques”
ISTITUTO STATALE DI ISTRUZIONE SUPERIORE F. ENRIQUES CORSO JAVA – PROVA FINALE DEL 21 MAGGIO 2007 NOME: COGNOME: ________________________________________________________________________________.
Corso JAVA Lezione n° 12 Istituto Statale di Istruzione Superiore “F. Enriques”
ISTITUTO STATALE DI ISTRUZIONE SUPERIORE F. ENRIQUES CORSO JAVA – PROVA INTERMEDIA DEL 12 MARZO 2007 NOME: COGNOME: ________________________________________________________________________________.
Conversione da base 10 a base X (Utilizzo della pila)
Fondamenti di Informatica 2 Ingegneria Informatica Docente: Giovanni Macchia a.a
1 FONDAMENTI DI INFORMATICA II Ingegneria Gestionale a.a ° Ciclo Approfondimenti sulle Classi.
Oggetti in C# Lezione 1 Classi ed istanze Oggetti in C# - Lezione 1.
JAVA Per iniziare. Verificare installazione javac –version java –version Cercare i files e sistemare eventualmente il path.
CORSO DI PROGRAMMAZIONE II Lezione 22
Una "vera" classe.. ..un esempio pratico: la calcolatrice
Programmazione ad oggetti
1 Un esempio con iteratore: le liste ordinate di interi.
Oggetti in C# Lezione 2 Metodi e Static Oggetti in C# - Lezione 2.
Variabili Numeriche –Interi (byte, short, int, long): complemento a 2 –A virgola mobile (float, double): IEEE 745 Alfanumeriche –Carattere (char): Unicode.
Ereditarieta’. Contenuti Introduciamo un meccanismo fondamentale di Java: l’ereditarieta’ Permette di estendere classi gia’ definite (ovvero di definire.
Esercitazione su Vector. Permette di definire collezioni di dati generiche, che sono in grado di memorizzare elementi di ogni sottotipo di Object Definito.
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE Puntatori Marco D. Santambrogio – Ver. aggiornata al 11 Ottobre 2014.
Università di Torino – Facoltà di Scienze MFN Corso di Studi in Informatica Programmazione I - corso B a.a prof. Viviana Bono Blocco 7 – Array.
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.
1 Eccezioni in Java. 2 Ricordiamo che 4 una procedura può terminare –normalmente, ritornando un risultato –in modo eccezionale ci possono essere diverse.
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE Puntatori Marco D. Santambrogio – Ver. aggiornata al 11 Marzo 2014.
ALLOCAZIONE STATICA: LIMITI Per quanto sappiamo finora, in C le variabili sono sempre dichiarate staticamente –la loro esistenza deve essere prevista e.
Cose nuove di Java (prima a chiacchiera, poi formalmente)
LIP: 2 Maggio 2008 Classi Astratte. Cos’e’ una Classe Astratta una classe astratta e’ un particolare tipo di classe permette di fornire una implementazione.
Sommario Oggetti immutabili e non Tipi Primitivi: String, Arrays.
Progettare una classe 21 Febbraio La classe BankAccount Vogliamo realizzare una classe i cui oggetti sono dei semplici conti bancari. * Identifichiamo.
LIP: 11 Maggio 2007 Classi Astratte. Cos’e’ una Classe Astratta una classe astratta e’ un particolare tipo di classe permette di fornire una implementazione.
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.
Introduzione all’Ereditarietà Pietro Palladino. Richiami UML Classe: descrizione di un insieme di oggetti software con caratteristiche simili Definisce.
Transcript della presentazione:

INNER CLASS Una Inner class è una classe la cui dichiarazione si trova all’ interno di un’ altra classe (La classe ospitante è detta top level): class A { . class InnerA { // codice di InnerA } // altro codice di A Per creare un oggetto di tipo InnerA si usa la seguente sintassi: A a=new A(); A.InnerA innerOb = a.new InnerA(); Se InnerA fosse stata a sua volta contenitrice di un’ altra classe B occorreva scrivere A.InnerA.B b=innerOb.new B();

Inner class (2) Confronto fra inner class e classi top-level Come anche le classi to level, le inner class non possono avere il nome uguale a quello di altre classi top level Possibilità di una inner class di essere privata, cioè invisibile all’ esterno della classe ospite(ma si può andare oltre, facendo si che essa sia visibile solo all’ interno di un singolo metodo; vedremo poi). Una classe top level non può mai essere privata. Se si cercasse comunque di accedere da una classe esterna E alla inner privata di A il compilatore replicherebbe: Top.java:15: Inner type InnerA in class A not accessible from class E. 3) La inner class puó accedere a tutti i metodi e i campi della classe ospitante (mentre la classe ospitante può vedere solo la parte pubblica della inner class) 4) Un oggetto di classe inner non può esistere se non esiste un oggetto della classe ospitante (se si fosse omessa l’ istruzione A a=new A(); il compilatore avrebbe protestato dicendo che non esiste un oggetto “a” di classe A per istanziarne uno della classe inner). 5) Come conseguenza del punto 4) una inner class non può avere campi statici Confronto con il C++: in C++ le classi inner non hanno la proprietà 3); sono quindi meno potenti che in java

il compilatore vedrà la inner class nel seguente modo: class InnerA { Come fa un oggetto di classe InnerA a utilizzare campi e metodi dell’ oggetto contenitore? In realtà il compilatore inserisce “segretamente” un riferimento all’ oggetto contenitore Supponendo che tale riferimento si chiami outer(in realtà non si chiama così; vedremo poi) il compilatore vedrà la inner class nel seguente modo: class InnerA { private outer A; InnerA( A a) { outer=a; } // non scrivere cosí in un programma vero! . outher.campoDiA; outer.metodoDiA(); A InnerA outer campoDiA NB: Non si può utilizzare outer in un programma(non è sintassi java!): si tratta solo di una rappresentazione interna del compilatore. Per riferirsi esplicitamente all’ oggetto contenitore bisogna usare la sintassi nomeClasseContenitore.this

Perché usare le inner class? Il riferimento esplicito all’ oggetto contenitore è necessario in caso si voglia accedere a un suo campo e questo campo e’ anche il nome di un campo di InnerA(cioé negli stessi casi in cui é obbligatorio usare this in una classe normale) : class A { int omonimo=5; class InnerA { int omonimo=2; public void stampaOmonimi() { System.out.println(omonimo); // stampa 2 System.out.println(A.this.omonimo); // stampa 5 } Se però ci si vuole riferire a un campo statico di A la notazione esplicita da usare è A.nomeCampoSatico(infatti i campi statici non appartengono a nessun oggetto, neanche all’ oggetto contenitore) Perché usare le inner class? Le inner class, sebbene prevedano una sintassi più complessa danno una certa semplicità strutturale. Si supponga ad esempio di voler realizzare uno stack di interi:

Esempio di uso delle inner class Supponendo di voler realizzare tale stack dinamicamente , è necessario creare una classe “LinkedNode”: classs LinkedNode { int info; LinkedNode next; } Tali campi dovranno inoltre essere pubblici per poter permettere il collegamento con il puntatore al top dello stack. Tuttavia non è opportuno che LinkedNode sia visibile anche all’ esterno della classe stack, in quanto tale classe è l’ unica a dover usare LinkedNode. Soluzione: rendiamo LinkedNode inner class privata di class:

class Stack { // stack di interi realizzato con la inner class LinkedNode first; private class LinkedNode { private int info; LinkedNode next; public int getInfo() { return info; } public void set(int x) { info=x; } } public boolean isEmpty() { return first==null; } public int top() { return first.getInfo(); } public void pop() { if(isEmpty()==false) first = first.next; } public void push(int x) { LinkedNode nuovo=new LinkedNode(); nuovo.set(x); nuovo.next=first; first=nuovo;

Inner class staiche Le inner class oltre a poter essere private possono anche essere di tipo static. Le inner class statiche non dipendono da istanze della classe contenitore e, per questo motivo, non hanno alcun riferimento implicito a oggetti di tale classe. Questo ha una conseguenza importante: tutti i campi non static della classe contenitore non sono accessibili alle i.c. statiche(quindi sono come le inner class del C++). (Top.java:11: Can't make a static reference to nonstatic variable a in class Top.) Tuttavia rispetto ad una classe top-level è possibile accedere a tutte le variabili statiche, anche quelle private. ATTENZIONE: che una inner class sia static non significa che essa non è instanziabile; significa solo(come detto sopra) che un oggetto di tale classe non dipende dall’ esistenza di istanze della classe base. Per creare un oggetto ob di una inner class statica StaticInn contenuta in una classe Top si usa la notazione Top.StaticInn ob=new Top.StaticInn(); Non è però scorretto scrivere Top.StaticInn ob=top.new StaticInn(); (top di tipo Top), ma la prima notazione è preferibile, in quanto rispecchia meglio la peculiarità delle i.c statiche di non dipendere da istanze. Nota finale: si può abbreviare la dichiarazione importando la classe contenitrice; esattamente come se si trattasse di un package; ad esmpio: import Top.StaticInn; /* ….. */ StaticInn ob=new StaticInn(); // senza Top.

Utilizzo di i.c statiche: esempio L’ uso principale delle i.c. statiche è di evitare conflitti di nomi. Si supponga di realizzare una classe che trovi il minimo e il massimo di un array, con due metodi (statici) int getMin(int a[]) e int getMax(int a[]) Se venisse invocato prima getMin() e poi getMax() sullo stesso array, occorrerebbero due scansioni dell’ array, mentre salta subito all’ occhio che si sarebbe potuto far tutto in una sola passata restituendo contemporaneamente sia il minimo che il massimo. Ciò potrebbe essere fatto creando una classe Pair contenenti due campi min e max e sostituendo i due metodi con un metodo getMinMax() che restituisca un oggetto di tipo Pair: Class Pair { int min; int max; } Class Esempio { …. // altro codice… static Pair getMinMax(int a[]) { // trova min e max di a[] e mette il risultato // in un oggetto Pair */ }

Il problema è che Pair è un nome piuttosto comune, e in un grosso progetto c’ è eventualità che qualche altro programmatore abbia usato una sua class Pair. Questa conflittualità di nomi può essere evitata rendendo la classe Pair(la nostra!) i.c di Esempio. In questa maniera tale classe sarà disponibile all’ esterno con la notazione più univoca Esempio.Pair : class Esempio { public static class Pair { int min; int max; Pair(int min, int max) { this.min=min; this.max=max; } } static Pair getMinMax() { . return Pair(min,max); // leggi note! Dall’ esterno si scriverà Esempio.Pair=Esempio.getMinMax(myArray) , senza possibilità di confusione con altre classi di nome Pair NB: se Pair non fosse static il ompilatore si lamenterebbe dicendo che non esiste alcun oggetto di tipo 'Eempio' per utilizzare o creare istanze della i.c Pair

Classi locali a metodi Può capitare che ad una inner class non siano interessati tutti i metodi della classe base, ma solo un metodo di quest’ ultima. Si può allora fare di piú: dichiarare la classe all’ interno del metodo stesso(classe locale). Una classe locale non solo non è visibile dall’ esterno, ma neanche dagli altri metodi della classe ospite. Per capire l’ utilizzo di simili classi(e quindi quello delle classi anonime) facciamo un esempio. Introduciamo una interfaccia “Propriety”: una proprietà è un qualcosa che ha un nome e un valore; quindi l’ interfaccia corrispondente sarà interface Propriety { String getNome(); String getValue(); } Si consideri ora una classe Impiegato, con i campi principali nome(String) e stipendio(int). Supponiamo che Impigato renda disponibile all’ esterno una salaryPropriety, cioè una proprietà che abbia come nome il nome dell’ impiegato e come valore il suo stipendio. Supponiamo che dall’ esterno sia possibile richiedere tale proprietà con il metodo Propriety getSalaryPropriety();

classi locali a metodi : esempio Come possiamo realizzare ció? Innanzi tutto notiamo una cosa importante: un oggetto di tipo SalarityPropriety appartiene esclusivamente a un impiegato; è pertanto conveniente cominciare a pensare di rendere SalarityPropriety una inner class di Impiegato(notare inoltre che in questa implementazione la classe SalarityPropriey sia priva di variabili proprie su cui chiamare getNome() e getValue(), poiché si hanno già a disposizione le variabili di Impiegato): class Impiegato { String nomeDip; double stipendio; private class SalarityPropriety implements Propriety { public String getNome() { return nome; } public String getVaue() { String val=“”; return val + stipendio; } } // altro… In realtà scopriamo che solo il metodo getSalarityPropriety() è interessato a tale classe (deve infatti eseguire l’ istruzione return new SalarityPropriety() ). Pertanto risulta più conveniente rendere SalarityPropriety classe locale di getSalarityPropriety():

classi locali a metodi : esempio(2) public Propriety getSalarityPropriety() { class SalarityPropriety() { // classe locale public String getNome() { return nome; } public String getValue() { /* vedi pag. precedente */ } } return new SalarityPropriety(); In questo modo abbiamo reso il codice ancora piú compatto.

Inner class vs Local class Entrambe possono accedere alle istanze della classe contenitrice (eventualmente con la notazione estesa NomeClasse.this) 2) Le classi locali hanno una minore visibilità: solo il metodo in cui sono scritte le può richiamare; per gli altri metodi della classe contenitrice sono invisibili 3) Maggiore compattezza del codice usando classi locali 4) Le classi locali possono accedere anche alle variabili locali del metodo in cui sono poste(non che ai parametri di esso), purchè tali varabili(o parametri) siano qualificate come final, e purchè la classe locale non possieda variabili omonime (che coprirebbero irrimediabilmente quelle locali; non è possibile infatti avere riferimenti a metodi). Il motivo per cui le variabili locali devono essere final è che le classi locali sono implementate creando in opportuni campi una copia di tali variabili(un po’ come quando si passa un parametro a una funzione) 5) Le classi locali non possono essere precedute dai modificatori come public o private, in quanto sono trattate come variabili locali

Classi anonime Riprendiamo l’ esempio della classe SalarityPrpriety vista prima: avevamo reso tale classe locale al metodo getSalaryPropriety: public Propriety getSalarityPropriety() { class SalarityPropriety() { // classe locale public String getNome() { return nome; } public String getValue() { /* vedi pag. precedente */ } } return new SalarityPropriety(); Osservando bene questo metodo notiamo che in realtà la classe SalarityPropriety non viene mai usata, se non per creare “al volo” e restituire un oggetto di tale classe: sarebbe più conciso restituire un oggetto di una nuova classe che implementi l’ interfaccia Propriety, ma senza preoccuparci di dare un nome a tale classe(che tanto non servirebbe, in quanto non visibile e quindi utilizzabile esternamente). In effetti ciò è possibile grazie alle classi anonime

classi anonime (2) public Propriety getSalaryPropriety() { return new Propriety() { // classe anonima… //… che implementa l’ interfaccia Propriety String getNome() { return nome; } String getValue() { String val=“”; return val+stipendio; } } Il senso di questa sintassi è quello di creare un nuovo oggetto di una nuova classe priva di nome che implementi l’ interfaccia Propriety. Esternamente, tale oggetto sarà utilizzabile come un oggetto di tipo Propriety, e il binding dinamico garantisce che verranno usati i metodi get() e set() come definiti sopra.

La sintassi generale delle classi anonime è new SupeType( <parametri di SuperType>) { // corpo della classe anonima } SuperType è una interfaccia(allora la classe anonima implementa l’ interfaccia) o una classe vera e propria(allora in questo caso la classe anonima estende tale classe). I parametri utilizzati durante la creazione della classe anonima sono forniti al costruttore della classe base, e non a quello della classe anonima . Questo perché una classe anonima non può avere un costruttore proprio; infatti il costruttore è un metodo che ha il nome della classe, ma una classe anonima non ha alcun nome(per definizione). Utilità delle classi anonime Le classi anonime sono in parte una buona idea, in quanto rendono il codice il più compatto possibile(c’ è meno “digitazione”); ma proprio tale compattezza può essere fonte di confusione. Conviene pertanto evitare, in nome della chiarezza l’ uso di tali classi se il codice da scrivere è di una certa lunghezza. Vediamo ora un uso un più reale delle classi anonime:

Nella programmazione a eventi si ha spesso la necessità di aggiungere a un componente oggetti che implementino interfacce come ActionListener o WindowListener: infatti un oggetto di questo tipo è in grado di “reagire” a eventi che derivano dalla manipolazione di quel componente. Ad esempio se il componente è una finestra, la chiusura della stessa dovrà causare una istruzione di chiusura del programma(che altrimenti resterebbe caricato in memoria); è pertanto necessario aggiungergli, tramite il metodo addWindowListener(WindowListener listener) un oggetto che implementi tale interfaccia, e in particolare il metodo windowClosing(WindowEvent e),il metodo invocato alla chiusura della finestra. In realtà non è necessario implementare tutti i metodi di WindowListener, in quanto la classe WindowAdapter implementa già tali metodi, che sono tutti vuoti. Pertanto se siamo interessati a catturare solamente l’ evento “chiusura della finestra” è sufficiente creare una classe che estenda WindowAdapter e ridefinisca windowClosing() affinché chiuda l’ intero programma. Il corpo di tale metodo è solitamente molto breve, e consiste della sola istruzione System.exit(0). Poiché l’ unico uso esterno che viene fatto di un oggetto di tale classe estesa è quello di essere creato e passato come parametro del metodo addWindowListener del componente, è comodo in questo caso fare uso di una classe anonima che estenda WindowAdapter: Component finestra=new JFrame(); crea una finestra finestra.addWindowListener(new WindowAdapter() { // classe anonima che estende // WindowAdapter windowClosing(WindowEvent e) { System.exit(0); } // ridefinisce il metodo });

Approfondimenti Si parlerà qui brevemente dell’ implementazione delle inner class. Innanzitutto le i.c. sono una questione tipica del compilatore: il compilatore crea due file separati .class(il nome del file per la classe inner è nomebase$nomeinner.class; se si tratta di una classe anonima il nome è nomebase$n, con n numero progressivo), e la macchina virtuale li tratta allo stesso modo, senza fare alcuna distinzione fra loro. Il compilatore deve quindi trasformare la inner class in una classe normale: nel fare ciò la prima cosa da fare è mettere un riferimento all’ oggetto ospite, solitamente nominato this$0 (il campo outer visto nei lucidi precedenti); ma ciò non basta ancora: è necessario dare alla inner class il privilegio di accedere ai campi privati dell’ oggetto ospite. Ciò viene realizzato inserendo nella classe contenitore dei metodi statici (assolutamente invisibili al programmatore) di nome access$0(), access$1(), etc. Questi metodi contengono sempre un riferimento ad un oggetto di tipo classe contenitore che individua l’ oggetto a cui si vuole accedere, e sono usati dalla inner class per accedere (in lettura o scrittura) ai metodi privati della classe base. In altre parole hanno una funzione di get() e set() per le variabili private dell’ ogggetto contenitore. Facciamo un esempio: consideriamo la funzione getValue() della classe SalarityProprety : l’ istruzione return val+stipendio verrebbe tradotta come return val+access$0(this$0), dove access$0 sarà del tipo double acces$0(Impiegato i) { return stipendio; }

Questo fatto rappresenta un rischio per la sicurezza: infatti si potrebbe usare i metodi access$ per accedere a informazioni private dell’ oggetto base. Naturalmente poiché i nomi sorgente non possono contenere caratteri speciali non basta collocare tale chiamata in un programma java e compilare: tuttavia per chi ha familiarità con i file .class è possibile scrivere un file .class con istruzioni macchina in grado di richiamare tali metodi. Riepilogando, se una inner class accede a dati privati è possibile accedere a questi anche tramite altre classi aggiunte al package, ma ciò richiede abilità e determinazione: non è possibile per un programmatore ottenere incidentalmente l’ accesso; egli deve creare esplicitamente un file di classe per ottener tale scopo. RIFERIMENTI: Castroman, Horell,”JAVA, fondamenti”, MacGrowHill (52,00 euro) AUTORE: NOME: Manni Stefano, EMAIL: mannistefano@inwind.it, mannistefano1981@libero.it TEL: 328-2165178; 011-5224485 /* EOF !! */