(e-book ita) java _ introduzione alla programmazione orientata ad oggetti in java

Upload: ritopipo1

Post on 03-Apr-2018

221 views

Category:

Documents


1 download

TRANSCRIPT

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    1/103

    Introduzione alla ProgrammazioneOrientata agli Oggetti in Java

    Versione 1.1

    Eugenio PoltoStefania Iaffaldano

    Ultimo aggiornamento: 1 Novembre 2003

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    2/103

    Copyright c

    2003 Eugenio Polto, Stefania Iaffaldano. All rights reserved.

    This document is free; you can redistribute it and/or modify it under the terms ofthe GNU General Public License as published by the Free Software Foundation; eitherversion 2 of the License, or (at your option) any later version.

    This document is distributed in the hope that it will be useful, but WITHOUT ANYWARRANTY;without even the implied warranty of MERCHANTABILITY or FITNESSFOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along with thisdocument; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,Boston, MA 02111-1307 USA.

    Sosteniamo la Cultura Libera:

    sosteniamo il Free Software

    Per la segnalazione di errori e suggerimenti, potete contattarci ai seguentiindirizzi:

    Web: http://www.eugeniopolito.it

    E-Mail: [email protected]

    Typeset with LATEX.

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    3/103

    Ringraziamenti

    Un grazie speciale ad OldDrake, Andy83 e Francesco Costa per ilprezioso aiuto che hanno offerto!

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    4/103

    Indice

    1 Introduzione 8

    I Teoria della OOP 9

    2 Le idee fondamentali 9

    2.1 Una breve storia della programmazione . . . . . . . . . . . . . . 92.2 I princpi della OOP . . . . . . . . . . . . . . . . . . . . . . . . . 122.3 ADT: creare nuovi tipi . . . . . . . . . . . . . . . . . . . . . . . 132.4 La classe: implementare gli ADT tramite lincapsulamento . . . . 152.5 Loggetto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162.6 Le relazioni fra le classi . . . . . . . . . . . . . . . . . . . . . . . 17

    2.6.1 Uso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172.6.2 Aggregazione . . . . . . . . . . . . . . . . . . . . . . . . 182.6.3 Ereditariet . . . . . . . . . . . . . . . . . . . . . . . . . 182.6.4 Classi astratte . . . . . . . . . . . . . . . . . . . . . . . . 22

    2.6.5 Ereditariet multipla . . . . . . . . . . . . . . . . . . . . 232.7 Binding dinamico e Polimorfismo . . . . . . . . . . . . . . . . . 27

    II La OOP in Java 29

    3 Classi e oggetti 293.1 Definire una classe . . . . . . . . . . . . . . . . . . . . . . . . . 293.2 Garantire lincapsulamento: metodi pubblici e attributi privati . . 293.3 Metodi ed attributi statici . . . . . . . . . . . . . . . . . . . . . . 313.4 Costruire un oggetto . . . . . . . . . . . . . . . . . . . . . . . . 32

    3.5 La classe Persona e loggetto eugenio . . . . . . . . . . . . . . 343.6 Realizzare le relazioni fra classi . . . . . . . . . . . . . . . . . . 37

    3.6.1 Uso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 373.6.2 Metodi static: un esempio . . . . . . . . . . . . . . . . 393.6.3 Aggregazione . . . . . . . . . . . . . . . . . . . . . . . . 413.6.4 Ereditariet . . . . . . . . . . . . . . . . . . . . . . . . . 44

    3.7 Classi astratte . . . . . . . . . . . . . . . . . . . . . . . . . . . . 523.8 Interfacce . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 563.9 Ereditariet multipla . . . . . . . . . . . . . . . . . . . . . . . . 60

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    5/103

    4 Le operazioni sugli oggetti 674.1 Copia e clonazione . . . . . . . . . . . . . . . . . . . . . . . . . 674.2 Confronto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 734.3 Binding dinamico . . . . . . . . . . . . . . . . . . . . . . . . . . 764.4 Serializzazione . . . . . . . . . . . . . . . . . . . . . . . . . . . 79

    III APPENDICI 83

    5 Una panoramica sul linguaggio 835.1 Tipi primitivi . . . . . . . . . . . . . . . . . . . . . . . . . . . . 835.2 Variabili . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 845.3 Operatori . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84

    5.3.1 Operatori Aritmetici . . . . . . . . . . . . . . . . . . . . 845.3.2 Operatori relazionali . . . . . . . . . . . . . . . . . . . . 855.3.3 Operatori booleani . . . . . . . . . . . . . . . . . . . . . 855.3.4 Operatori su bit . . . . . . . . . . . . . . . . . . . . . . . 85

    5.4 Blocchi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86

    5.5 Controllo del flusso . . . . . . . . . . . . . . . . . . . . . . . . . 865.6 Operazioni (Metodi) . . . . . . . . . . . . . . . . . . . . . . . . 875.6.1 Il main . . . . . . . . . . . . . . . . . . . . . . . . . . . 895.6.2 I package . . . . . . . . . . . . . . . . . . . . . . . . . . 895.6.3 Gli stream . . . . . . . . . . . . . . . . . . . . . . . . . . 905.6.4 LI/O a linea di comando . . . . . . . . . . . . . . . . . . 915.6.5 Le eccezioni . . . . . . . . . . . . . . . . . . . . . . . . 915.6.6 Installazione del JDK . . . . . . . . . . . . . . . . . . . . 93

    6 La licenza GNU GPL 94

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    6/103

    Elenco delle figure

    1 Una classe in UML. . . . . . . . . . . . . . . . . . . . . . . . . . 152 La classe Persona in UML. . . . . . . . . . . . . . . . . . . . . 163 La relazione duso in UML. . . . . . . . . . . . . . . . . . . . . . 174 La relazione di aggregazione in UML. . . . . . . . . . . . . . . . 185 La relazione di ereditariet in UML. . . . . . . . . . . . . . . . . 196 La classe delle persone come sottoclasse della classe degli animali. 20

    7 Una piccola gerarchia di Animali. . . . . . . . . . . . . . . . . . 218 Una piccola gerarchia di Animali in UML. . . . . . . . . . . . . . 219 Matrimonio fra classe concreta e astratta . . . . . . . . . . . . . 2310 Composizione: la classe Studente Lavoratore . . . . . . . . . 2311 Studente Lavoratore come aggregazione e specializzazione . . 2412 Studente Lavoratore come aggregazione . . . . . . . . . . . . 2513 Lex Studente ed ex Lavoratore ora Disoccupato . . . . . . . 2514 La classe Studente come sottoclasse di Persona . . . . . . . . . 2715 Loggetto primo appena creato . . . . . . . . . . . . . . . . . . . 3316 Loggetto primo non ancora creato . . . . . . . . . . . . . . . . . 33

    17 Loggetto eugenio dopo la costruzione . . . . . . . . . . . . . . 3518 Esecuzione del programma Applicazione.java . . . . . . . . . 5119 Esecuzione del programma Applicazione.java . . . . . . . . . 5520 Diagramma UML per interface . . . . . . . . . . . . . . . . . 5621 Diagramma UML per implements . . . . . . . . . . . . . . . . . 5922 Diagramma UML per il matrimonio fra classe concreta ed inter-

    faccia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6023 Una Pila di numeri interi . . . . . . . . . . . . . . . . . . . . . . 6024 Esecuzione di ProvaPila . . . . . . . . . . . . . . . . . . . . . . 6425 Gli oggetti primo e secondo dopo la creazione . . . . . . . . . . 69

    26 Gli oggetti primo e secondo dopo lassegnamento secondo =primo; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6927 Gli oggetti primo e secondo dopo la clonazione . . . . . . . . . . 7128 Gli oggetti primo e secondo dopo listruzione secondo.set(16); 7229 Un oggetto ha sempre un riferimento implicito ad Object . . . . . 7430 Loggetto bill istanza di Cane . . . . . . . . . . . . . . . . . . . 7531 base = derivata; . . . . . . . . . . . . . . . . . . . . . . . . . 7832 Passaggio dei parametri ad una funzione . . . . . . . . . . . . . . 88

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    7/103

    Elenco delle tabelle

    1 Pro e contro delluso di ereditariet e aggregazione . . . . . . . . 202 Tipi primitivi di Java . . . . . . . . . . . . . . . . . . . . . . . . 83

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    8/103

    1 INTRODUZIONE 8

    1 Introduzione

    Questa trattazione sulla Programmazione Orientata agli Oggetti o Object Ori-ented Programming (OOP in seguito) inJava nasce dallosservazione che, moltospesso, i manuali sono degli ottimi reference (cfr. [3]) del linguaggio ma non ap-profondiscono i pochi ma essenziali concetti della OOP; daltra parte nei corsiuniversitari si presta fin troppa attenzione alla teoria senza approfondire gli aspettiimplementativi.

    Quindi si cercher di trattare sia la teoria che la pratica della OOP perch entram-bi gli aspetti sono fondamentali per poter scrivere un buon codice orientato aglioggetti.Purtroppo Java viene considerato (in modo errato!) un linguaggio per scriveresoltanto applet o addirittura viene confuso con il linguaggio di script JavaScript:con Java si possono scrivere delle applicazioni standalone che non hanno moltoda invidiare (a livello di prestazioni) ai programmi scritti con altri linguaggi OOPpi efficienti come C++. Infatti, attualmente, la Java Virtual Machine (cio lostrato software che si occupa di trasformare il codice intermedio o bytecode inchiamate alle funzioni del Sistema Operativo - syscall) consente di avere delle

    ottime prestazioni.In [1] potete trovare la versione 1.4 del JDK. importante sottolineare che questo non un manuale sul linguaggio, ma unatrattazione sullimpostazione Object Oriented del linguaggio: comunque, se nonsi conosce la sintassi di Java, consigliabile dare uno sguardo alla sezione 5 dove disponibile un veloce riassunto sulla struttura del linguaggio.

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    9/103

    9

    Parte I

    Teoria della OOPIn questa parte verranno introdotte e discusse le idee fondamentali della OOP. Sesi conoscono gi i princpi ed i meccanismi della OOP si pu passare alla partesuccessiva, dove si discute come tali concetti sono realizzati in Java.

    2 Le idee fondamentali

    2.1 Una breve storia della programmazione

    La programmazione dei computer esiste ormai da circa 60 anni. Ovviamente inun tempo cos lungo, ha subto notevoli cambiamenti: agli albori larte di pro-grammare consisteva nella programmazione di ogni singolo bit di informazionetramite degli interruttori che venivano accesi e spenti. Quindi il programma era inrealt una sequenza di accensioni e spegnimenti di interruttori che producevano il

    risultato che si voleva, anzi che si sperava di ottenere: pensate cosa poteva com-portare lo scambio di una accensione con uno spegnimento o viceversa!Solo intorno al 1960 venne scritto il primo Assembler: questo linguaggio era (ed) troppo legato alla struttura del microprocessore e soprattutto era (ed ) diffi-cile scrivere un programma con un linguaggio troppo vicino alla macchina e pocoamichevole per luomo.Tra il 1969 ed il 1971, Dennis Ritchie scrisse il primo linguaggio di program-mazione ad alto livello: il C. Seppure ad un gradino superiore allassembler esoprattutto il codice sorgente di un programma pu essere ricompilato su qualsi-asi piattaforma (con qualche modifica!), questo linguaggio risulta ancora troppovicino alla macchina (basti pensare che i Sistemi Operativi sono scritti in Ce As-sembler).Nel 1983Bijarne Stroustrup (programmatore presso la compagnia telefonica amer-icana Bell Laboratories) ebbe la necessit di dover simulare un sistema telefonico:i linguaggi allora disponibili si prestavano poco a programmare un sistema coscomplesso, cos ebbe lidea di partire dal Cper scrivere un nuovo linguaggio chesupportasse le classi. Nacque cos il C con oggetti. Lidea di classe era gi notaed utilizzata in altri linguaggi come Smalltalk.Tuttavia il C con oggetti (in seguito rinominato C++) una estensione del C equindi ha dei pregi e dei difetti:

    pro fra i pregi possiamo sicuramente annoverare lefficienza (propria di C) e laportabilit del codice sorgente (con qualche modifica) da una archittet-tura ad unaltra: i compilatori C++ esistono per ogni tipo di piattaforma

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    10/103

    2 LE IDEE FONDAMENTALI 10

    hardware, pertanto sufficiente qualche modifica al codice sorgente ed unaricompilazione;

    contro la gestione della memoria, per esempio, completamente a carico delprogrammatore e, come si sa, la gestione dei puntatori una fabbrica dierrori. inoltre possibile mixare sia codice C che codice C++, ottenendo cos uncodice non molto pulito dal punto di vista della OOP: supponiamo di volere

    confrontare due variabili a e b. Il codice corretto il seguente:

    if (a == b) {...}

    Ma basta omettere un = per ottenere un assegnamento:

    if (a = b) {...}

    se lassegnamento va a buon fine, viene eseguito il blocco di istruzioni. Unerrore del genere pu essere frequente: se non usato bene, il C++ rischia di

    essere un boomerang per il programmatore.Nei primi mesi del 1996 venne presentata la prima versione del linguaggio Javache introduceva non poche novit:

    macchina virtuale anche se non era un concetto nuovo nellinformatica (gi IBMaveva fatto delle sperimentazioni sulle Virtual Machine in un Sistema Oper-ativo proprietario), lidea di sfruttare una Macchina Virtuale o Java VirtualMachine - JVM che si interpone fra il linguaggio intermedio bytecode edil linguaggio macchina della architettura sottostante era una novit assoluta.Tale idea stata ultimamente ripresa da una nota Software House con un

    progetto denominato .NET . . .portabilit grazie al concetto di Virtual Machine sufficiente compilare una so-

    la volta il programma per poi eseguire il programma .class in formato dibytecode su qualsiasi altra piattaforma; per C++ vale solo una portabilit dicodice sorgente e non di programma eseguibile;

    esecuzione di programmi nei browser (applet) si pu scrivere una unica appli-cazione che venga eseguita sia in modo nativo che allinterno di un browserweb;

    gestione automatica della memoria questo sicuramente uno degli aspetti piimportanti di Java. Ci preoccupiamo solo della costruzione di un oggetto,perch la distruzione completamente gestita dalla JVMtramite il Garbage

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    11/103

    2 LE IDEE FONDAMENTALI 11

    Collector: un oggetto non pi utilizzato viene automaticamente distrutto.Inoltre in Java esiste solo il concetto di riferimento ad un oggetto checomporta una gestione semplice della notazione (si pensi alla notazione . o-> di C++ a seconda che un metodo sia richiamato su una variabile oggetto/ reference o su un puntatore). Lassenza della gestione diretta dei puntatoriconsente di produrre un codice sicuro.

    Per un confronto fra Java e C++ cfr. [4].

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    12/103

    2 LE IDEE FONDAMENTALI 12

    2.2 I princpi della OOP

    La OOP una evoluzione naturale dei linguaggi di programmazione: essa nascecon lo scopo preciso di simulare e modellare la realt. I princpi su cui si basa laOOP sono semplici ma molto potenti:

    Definire nuovi tipi di dati.

    Incapsulare i valori e le operazioni.

    Riusare il codice esistente (ereditariet).

    Fornire il polimorfismo.

    Come vedremo, nella OOP non si fa differenza fra valori ed operazioni: sem-plicemente si parla di Tipo di dato che ingloba le due entit in ununica struttura.Quindi necessario definire un nuovo Tipo di dato. altrettanto necessario accedere ad un valore di un tipo di dato: come vedremoquesto fattibile tramite il meccanismo di incapsulamento.Un altro cardine della OOP il riuso del codice: cio utilizzare del codice es-

    istente per poterlo specializzare.Il polimorfismo si rende necessario, come vedremo, in una gerarchia di eredita-riet.

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    13/103

    2 LE IDEE FONDAMENTALI 13

    2.3 ADT: creare nuovi tipi

    Un Tipo di Dato Astratto o Abstract Data Type - ADT , per definizione, unnuovo tipo di dato che estende i tipi nativi forniti dal linguaggio di program-mazione.Un ADT caratterizzato da un insieme di:

    dati;

    operazioni che agiscono sui dati, leggengoli/scrivendoli;Fin qui niente di nuovo: anche i linguaggi procedurali, come per esempio C, con-sentono di definire un ADT. Ma, mentre per tali linguaggi chiunque pu avereaccesso ai dati e modificarli, i linguaggi Object Orientedne garantiscono la lororiservatezza.Supponiamo infatti di voler definire in C(non preoccuparsi della sintassi) un ADTPersona cio una struttura dati che mantenga le informazioni (dati) di una Per-sona, come, per esempio, il nome, il cognome e la data di nascita e che consentadi creare e stampare le informazioni di una persona (operazioni):

    /* Struttura dati per mantenere la data di nascita */

    struct Data {

    int giorno;

    int mese;

    int anno;

    };

    /* Struttura dati per mantenere le info. della persona */

    struct Persona {

    struct Data *data_di_nascita;

    char *nome;

    char *cognome;

    };

    /* Setta le info. della persona */

    void creaPersona(struct Persona *persona)

    {

    persona->data_di_nascita->giorno = 31;

    persona->data_di_nascita->mese = 12;

    persona->data_di_nascita->anno = 1976;

    persona->nome = "Eugenio";

    persona->cognome = "Polito";}

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    14/103

    2 LE IDEE FONDAMENTALI 14

    /* Stampa le info. della persona */

    void stampaDati(struct Persona *persona)

    {

    printf("Mi chiamo %s %s e sono nato il %i-%i-%i \n",

    persona->nome,

    persona->cognome,

    persona->data_di_nascita->giorno,

    persona->data_di_nascita->mese,

    persona->data_di_nascita->anno);

    }

    /* crea un puntatore alla struttura e lo inizializza;

    quindi stampa le info. */

    int main()

    {

    struct Persona *io;

    creaPersona(io);

    stampaDati(io);

    return 0;}

    Se eseguiamo questo programma, otteniamo il seguente output:

    Mi chiamo Eugenio Polito e sono nato il 31-12-1976

    Proviamo adesso a modificare il main nel seguente modo:

    int main()

    {

    struct Persona *io;creaPersona(io);

    io->data_di_nascita->mese = 2;

    stampaDati(io);

    return 0;

    }

    Questa volta loutput :

    Mi chiamo Eugenio Polito e sono nato il 31-2-1976

    Cio le mie informazioni private sono state modificate con lassegnamento:

    io->data_di_nascita->mese = 2

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    15/103

    2 LE IDEE FONDAMENTALI 15

    2.4 La classe: implementare gli ADT tramite lincapsulamento

    La classe consente di implementare gli ADT attraverso il meccanismo di incap-sulamento: i dati devono rimanere privati insieme allimplementazione e sololinterfaccia delle operazioni resa pubblica allesterno della classe.Questo approccio fondamentale per garantire che nessuno possa accedere alleinformazioni della classe e quindi, dal punto di vista del programmatore, unagaranzia per non fare errori nella stesura del codice: basti pensare allesempio

    dellADT Persona visto prima. Se i dati fossero stati privati non avrei potutoliberamente modificare la data di nascita nel main. Quindi, ricapitolando, unaclasse implementa un ADT (un sinonimo di classe proprio tipo) attraverso ilmeccanismo di incapsulamento.La descrizione di una classe deve elencare:

    i dati (o attributi): contengono le informazioni di un oggetto;

    le operazioni (o metodi): consentono di leggere/scrivere gli attributi di un ogget-to;

    Quando si scrive una applicazione buona norma iniziare con la progettazionedellapplicazione stessa; Grady Booch identifica i seguenti obiettivi in questa fase:

    identificare le classi;

    identificare le funzionalit di queste classi;

    trovare le relazioni fra le classi;

    Questo processo non pu che essere iterativo.Nella fase di progettazione si usa un formalismo grafico per rappresentare leclassi e le relazioni fra di esse: lUML - Unified Modeling Language.

    In UML una classe si rappresenta cos:

    Qui vanno messigli attributi

    Qui vanno messi

    Qui va il nomedella classe

    i metodi

    Figura 1: Una classe in UML.

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    16/103

    2 LE IDEE FONDAMENTALI 16

    Quindi la classe Persona in UML cos rappresentata:

    Figura 2: La classe Persona in UML.

    2.5 Loggetto

    Che cos quindi un oggetto?Per definizione, diciamo che un oggetto una istanza di una classe. Quindi unoggetto deve essere conforme alla descrizione di una classe.Un oggetto pertanto contraddistinto da:

    1. attributi;2. metodi;

    3. identit;

    Allora se abbiamo una classe Persona, possiamo creare loggetto eugenio che una istanza di Persona. Tale oggetto avr degli attributi come, per esempio, nome,cognome e data di nascita; avr dei metodi come creaPersona(...), stam-paDati(...), etc. Inoltre avr una identit che lo contraddistingue da un even-tuale fratello gemello, diciamo pippo (anche lui ovviamente istanza di Persona).

    Per il meccanismo di incapsulamento un oggetto non deve mai manipolare di-rettamente i dati di un altro oggetto: la comunicazione deve avvenire tramitemessaggi (cio chiamate a metodi). I client devono inviare messaggi ai server!Quindi nellesempio di prima: se il fratello gemello pippo, in un momento diamnesia, vuole sapere quando nato eugenio deve inviargli un messaggio, ciodeve richiamare un metodo ottieniDataDiNascita(...) .Quindi, ricapitolando, possiamo dire che:

    la classe una entit statica cio a tempo di compilazione;

    loggetto una entit dinamica cio a tempo di esecuzione (run time);

    Nella sezione 4 vedremo come gli oggetti vengono gestiti in Java.

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    17/103

    2 LE IDEE FONDAMENTALI 17

    2.6 Le relazioni fra le classi

    Un aspetto importante della OOP la possibilit di definire delle relazioni fra leclassi per riuscire a simulare e modellare il mondo che ci circonda :

    uso: una classe pu usare oggetti di unaltra classe;

    aggregazione: una classe pu avere oggetti di unaltra classe;

    ereditariet: una classe pu estendere unaltra classe.

    Vediamole in dettaglio singolarmente.

    2.6.1 Uso

    Luso o associazione la relazione pi semplice che intercorre fra due classi.Per definizione diciamo che una classe A usa una classe B se:

    - un metodo della classe A invia messaggi agli oggetti della classe B, oppure

    - un metodo della classe A crea, restituisce, riceve oggetti della classe B.

    Per esempio loggetto eugenio (istanza di Persona) usa loggetto phobos (is-tanza di Computer) per programmare: quindi loggetto eugenio ha un meto-do (diciamo programma(...)) che usa phobos (tale oggetto avr per esempioun metodo scrivi(...)). Osserviamo ancra che in questo modo lincapsula-mento garantito: infatti eugenio non pu accedere direttamente agli attributiprivati di phobos, come ram o bus ( il Sistema Operativo che gestisce talirisorse). Questo discorso pu valere per Linux che nasconde bene le risorse,ma non pu valere per altri Sistemi Operativi che avvertono lavvenuto accesso aparti di memoria riservate al kernel ed invitano a resettare il computer. . .

    In UML questa relazione si rappresenta cos:

    Figura 3: La relazione duso in UML.

    Per la realizzazione di questa relazione in Java vedere la sezione 3.6.1.

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    18/103

    2 LE IDEE FONDAMENTALI 18

    2.6.2 Aggregazione

    Per definizione si dice che una classe A aggrega (contiene) oggetti di una classeB quando la classe A contiene oggetti della classe B. Pertanto tale relazione uncaso speciale della relazione di uso. Sugli oggetti aggregati sar possibile chia-mare tutti i metodi, ma ovviamente non sar possibile accedere agli attributi (lin-capsulamento continua a regnare!).N.B.: la relazione di aggregazione viene anche chiamata relazione has-a o ha-un.

    Ritorniamo al nostro esempio della classe Persona: come si detto una personaha una data di nascita. Risulta pertanto immediato e spontaneo aggregare unoggetto della classe Data nella classe Persona!In UML la relazione A aggrega B si disegna cos:

    Figura 4: La relazione di aggregazione in UML.

    Notare che il rombo attaccato alla classe che contiene laltra.Un oggetto aggregato semplicemente un attributo!Vi rimando alla sezione 3.6.3 per la realizzazione in Java di tale relazione.

    2.6.3 Ereditariet

    Questa relazione (anche detta inheritance o specializzazione) sicuramente la piimportante perch rende possibile il riuso del codice.Si dice che una classe D (detta la classe derivata o sottoclasse) eredita da unaclasse B (detta la classe base o superclasse) se gli oggetti di D formano un sot-

    toinsieme degli oggetti della classe base B. Tale relazione anche detta relazioneis-a o -un. Inoltre si dice che D un sottotipo di B.Da questa definizione possiamo osservare che la relazione di ereditariet larelazione binaria di sottoinsieme

    , cio:

    D

    A

    Sappiamo che

    una relazione che gode della propriet transitiva:

    C

    B

    A

    C

    A

    Pertanto la relazione di ereditariet transitiva!Nasce spontaneo domandarsi perch vale

    e non vale

    .

    Il motivo presto detto: la relazione

    una relazione dordine fra insiemi, quindigode di tre propriet:

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    19/103

    2 LE IDEE FONDAMENTALI 19

    1. riflessiva: A

    A

    2. antisimmetrica: A

    B

    B

    A

    A

    B

    3. transitiva: C

    B

    B

    A

    C

    A

    Ma riflettendo sul concetto di ereditariet, affinch si verifichi la 1. dovrebbesuccedere che una classe erediti da se stessa, cio la classe dovrebbe essere unaclasse derivata da se stessa: impossibile!Analogamente la propriet 2. dice che una classe una classe base ed una classederivata allo stesso tempo: anche questo impossibile! Quindi vale solo la 3.D eredita da B, in UML, si disegna cos:

    Figura 5: La relazione di ereditariet in UML.

    Vediamo adesso perch con lereditariet si ottiene il riuso del codice.Consideriamo una classe base B che ha un metodo f(...) ed una classe derivataD che eredita da B. La classe D pu usare il metodo f(...) in tre modi:

    lo eredita: quindi f(...) pu essere usato come se fosse un metodo di D;

    lo riscrive (override): cio si da un nuovo significato al metodo riscrivendo lasua implementazione nella classe derivata, in modo che tale metodo eseguauna azione diversa;

    lo estende: cio richiama il metodo f(...) della classe base ed aggiunge altreoperazioni.

    immediato, pertanto, osservare che la classe derivata pu risultare pi grandedella classe base relativamente alle operazioni ed agli attributi. La classe derivata

    non potr accedere agli attributi della classe base, anche se li eredita, proprio pergarantire lincapsulamento. Tuttavia, come vedremo, possibile avere un accesso

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    20/103

    2 LE IDEE FONDAMENTALI 20

    controllato agli attributi della classe base da una classe derivata. importante notare che lereditariet pu essere simulata con laggregazione(cio is-a diventa has-a)!Ovviamente ci sono dei pro e dei contro, che possiamo riassumere cos:

    Ereditariet Aggregazione

    Pro Propolimorfismo e binding dinamico chiusura dei moduli

    Contro Controlegame stretto fra classe riscrittura dei metodibase e derivata nella classe derivata

    Tabella 1: Pro e contro delluso di ereditariet e aggregazione

    Java non supporta linheritance multiplo quindi necessario ricorrere allag-gregazione (vedere la sottosezione successiva 2.6.5).

    Riprendiamo la classe Persona: pensandoci bene tale classe deriva da unaclasse molto pi grande, cio la classe degli Animali:

    An ma

    Persone

    Cani

    Figura 6: La classe delle persone come sottoclasse della classe degli animali.

    Quindi ogni Persona un Animale; un oggetto di tipo Persona, come euge-nio, anche un Animale. Cos come il mio cane bill un oggetto di tipo Caneed anche lui fa parte della classe Animale.Riflettiamo adesso sulle operazioni (metodi) che pu fare un Animale: un animalepu mangiare, dormire, cacciare, correre, etc.Una Persona un Animale: di conseguenza eredita tutte le operazioni che pufare un Animale. Lo stesso vale per la classe Cane. Ma sorge a questo punto unadomanda: una Persona mangia come un Cane? La risposta ovviamente No!Infatti una Persona per poter mangiare usa le proprie mani, a differenza del Caneche fa tutto con la bocca e le zampe: quindi loperazione del mangiare deve essereridefinita nella classe Persona!

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    21/103

    2 LE IDEE FONDAMENTALI 21

    Inoltre possiamo pensare a cosa possa fare in pi una Persona rispetto ad unAnimale: pu parlare, costruire, studiare, fare le guerre, inquinare... etc.Quindi nella classe derivata si possono aggiungere nuove operazioni!Si detto precedentemente che la relazione di ereditariet transitiva: verifichi-amo quanto detto con un esempio.Pensiamo ancora alle classe Animale: come ci insegna Quark (...e la ScuolaElementare. . . ) il mondo Animale composto da sottoclassi come la classe deiMammiferi, degli Anfbi, degli Insetti, etc. La classe dei Mammiferi a suavolta composta dalla classe degli Esseri Umani, dei Cani, delle Balene, etc.:

    An ma

    Mammiferi

    CaniUmaniEsseri

    Insetti

    Alati

    Non Alati

    Figura 7: Una piccola gerarchia di Animali.

    Ripensiamo adesso al Cane: tale classe una sottoclasse di Mammifero che asua volta una sottoclasse di Animale, in UML:

    Figura 8: Una piccola gerarchia di Animali in UML.

    Pertanto ogni Cane un Mammifero e, poich ogni Mammifero un Animale,concludiamo che un Cane un Animale! Pertanto ogni Cane potr fare ogni op-erazione definita nella classe Animale.Con questo esempio abbiamo anche introdotto il concetto di gerarchia di classi,che, per definzione, un insieme di classi che estendono una classe base comune.

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    22/103

    2 LE IDEE FONDAMENTALI 22

    2.6.4 Classi astratte

    Riprendiamo lesempio di Figura 8 ed esaminiamo i metodi della classe baseAnimale: consideriamo, per esempio, loperazione comunica(...). Se pen-siamo ad un Cane tale operazione viene eseguita attraverso le espressioni dellafaccia, del corpo, della coda. Un Essere Umano pu espletare tale operazionr inmodo diverso: attraverso i gesti, le espressioni facciali, la parola. Un Delfino,invece, comunica attraverso le onde sonore.

    Allora che cosa significa tutto questo? Semplicemente stiamo dicendo che loper-azione comunica(...) non sappiamo come pu essere realizzata nella classe

    base! Un discorso analogo pu essere fatto per loperazione mangia(...).In sostanza sappiamo che questi metodi esistono per tutte le classi che derivanoda Animale e che sono proprio tali classi a sapere come realizzare (implementare)questi metodi.I metodi come comunica(...), mangia(...) etc., si dicono metodi astratti ometodi differiti: cio si dichiarano nella classe base, ma non vengono implemen-tati; saranno le classi derivate a sapere come implementare tali operazioni.Una classe che ha almeno un metodo astratto si dice classe astratta e deve essere

    dichiarata tale. Una classe astratta pu anche contenere dei metodi non astratti(concreti)!Nella sezione 3.7 vedremo come dichiararle e usarle in Java.Attraverso delle considerazioni siamo arrivati a definire la classe Animale comeclasse astratta.Riflettiamo un momento sul significato di questa definizione: creare oggetti dellaclasse Animale serve a ben poco, proprio perch tale classe fin troppo genericaper essere istanziata. Piuttosto pu essere usata come un contenitore di com-portamenti (operazioni) comuni che ogni classe derivata sa come implementare!Questo un altro punto fondamentale della OOP:

    bene individuare le operazioni comuni per poterle posizionare al livellopi alto nella gerarchia di ereditariet.

    La classe Cane, Delfino etc., implementeranno ogni operazione astratta, proprioperch ognuna di queste classi sa come fare per svolgere le operazioni ereditatedalla classe base.

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    23/103

    2 LE IDEE FONDAMENTALI 23

    2.6.5 Ereditariet multipla

    Nella sottosezione 2.6.3 si parlato della relazione di ereditariet fra due classi.Questa relazione pu essere estesa a pi classi.Esistono tre forme di ereditariet multipla:

    matrimonio fra una classe concreta ed una astratta: per esempio:

    Figura 9: Matrimonio fra classe concreta e astratta

    Quindi Stack la classe astratta che definisce le operazioni push(...),pop(...), etc. La classe array serve per la manipolazione degli array.Pertanto la Pila implementa le operazioni dello Stack e le richiama su unarray.

    duplice sottotipo: una classe implementa due interfacce filtrate.

    composizione: una classe estende due o pi classi concrete. proprio questocaso che genera alcuni problemi.Consideriamo il classico esempio (cfr. [2]) della classe Studente Lavo-ratore: questa classe estende la classe Studente e Lavoratore (en-trambe estendono la classe Persona):

    Figura 10: Composizione: la classe Studente Lavoratore

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    24/103

    2 LE IDEE FONDAMENTALI 24

    La classe Persona ha degli attributi, come nome, cognome, data di na-scita etc., e dei metodi, come, per esempio, mangia(...). Sia la classeStudente che la classe Lavoratore estendono la classe Persona, quin-di erediteranno sia attributi che metodi. Supponiamo di creare loggettoeugenio come istanza di Studente Lavoratore e richiamiamo su di es-so il metodo mangia(...). Purtroppo tale metodo esiste sia nella classeStudente che nella classe Lavoratore: quale metodo sar usato? Nessunodei due perch il compilatore riporter un errore in fase di compilazione!

    Analogamente i membri saranno duplicati perch saranno ereditati da en-trambe le classi (Studente e Lavoratore): eugenio si ritrover con duenomi, due cognomi e due date di nascita.I progettisti di Java, proprio per evitare simili problemi, hanno deciso dinon supportare la composione come forma di ereditariet multipla.Per, come si detto nella sezione 2.6.3, lereditariet pu essere simulatacon laggregazione, pertanto il diagramma UML di Figura 10 pu esserecos ridisegnato:

    Figura 11: Studente Lavoratore come aggregazione e specializzazione

    Adesso lo Studente Lavoratore eredita un solo metodo mangia(...),dorme(...), etc., cos come avr un solo nome, cognome, etc.Se eugenio deve lavorare(. . . ) richiamer il metodo omonimo sulloggettoaggregato istanza di Lavoratore.Questo esempio porta ad unaltra riflessione importante: ma eugenio sarsempre uno Studente? Si spera di no. . . Prima o poi finir di studiare!Come si detto in Tabella 1, lereditariet ha lo svantaggio di stabilire unlegame troppo forte tra classe base e derivata. Ci significa che loggettoeugenio (che magari continua a vivere nella societ in qualit di Lavorato-re), anche quando non sar pi uno Studente, potr invocare il metodofaiLaFilaInSegreteria(...) o ricopiaAppunti(...) , perch con-

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    25/103

    2 LE IDEE FONDAMENTALI 25

    tinua ad essere uno Studente, secondo la gerarchia di Figura 11!Risulta immediato cambiare nuovamente lereditariet con laggregazione:

    Figura 12: Studente Lavoratore come aggregazione

    In questo modo, ad esempio, il metodo faiLaFilaInSegreteria(...)viene richiamato sulloggetto aggregato istanza di Studente. Quando eu-genio non sar pi Studente, loggetto aggregato istanza di Studente

    verr eliminato (tanto un semplice attributo!).Se poi malauguratamente eugenio perde il proprio lavoro, non aggrega pila classe Lavoratore: pu comunque aggregare una nuova classe, comeper esempio Disoccupato:

    Figura 13: Lex Studente ed ex Lavoratore ora Disoccupato

    Perch abbiamo aggregato una nuova classe (Disoccupato)? Se guardiamola Figura 11 si ha (per la transitivit della relazione di ereditariet):Studente Lavoratore

    Studente

    Persona

    Studente Lavoratore Persona.Quindi ogni Studente Lavoratore pu invocare il metodo mangia(...)della classe Persona (lo eredita).Analogamente, in Figura 11, vediamo che sia Studente che Lavoratoreereditano da Persona. Quindi uno Studente Lavoratore pu invocare ilmetodo mangia(...) sia sulloggetto aggregato istanza di Studente chesulloggetto aggregato istanza di Lavoratore.

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    26/103

    2 LE IDEE FONDAMENTALI 26

    Ma se un oggetto di classe Studente Lavoratore termina di studiare eperde il lavoro (cio eliminiamo gli attributi, oggetti di tipo Studente eLavoratore) potr continuare a mangiare? Risposta: No! Ecco spie-gato il motivo per cui stata aggregata una nuova classe in StudenteLavoratore.

    Ricapitolando:

    Lereditariet multipla sottoforma di composizione pu essere modellatacon laggregazione e con lereditariet singola. bene usare questa com-binazione per non incorrere in problemi seri durante la stesura del codice.

    Usare lereditariet solo quando il legame fra la classe base e la classederivata per sempre, cio dura per tutta la vita degli oggetti, istanzedella classe derivata. Se tale legame non duraturo meglio usare lag-gregazione al posto della specializzazione.

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    27/103

    2 LE IDEE FONDAMENTALI 27

    2.7 Binding dinamico e Polimorfismo

    La parola polimorfismo deriva dal greco e significa letteralmente molte forme.Nella OOP tale termine si riferisce ai metodi: per definizione, il polimorfismo la capacit di un oggetto, la cui classe fa parte di una gerarchia, di chiamare la

    versione corretta di un metodo.Quindi il polimorfismo necessario quando si ha una gerarchia di classi.Consideriamo il seguente esempio:

    Figura 14: La classe Studente come sottoclasse di Persona

    Nella classe base Persona definito il metodo calcolaSomma(...), che,per esempio, esegue la somma sui naturali 2+2 e restituisce 5 (in 3 vedremo comepassare argomenti ad un metodo e restituire valori); la classe derivata Studenteinvece riscrive il metodo calcolaSomma(...) ed esegue la somma sui naturali2+2 in modo corretto, restituendo 4.N.B. Il metodo deve avere lo stesso nome, parametri e tipo di ritorno in ogniclasse, altrimenti non ha senso parlare di polimorfismo.Creiamo adesso loggetto eugenio come istanza di Studente ed applichiamo ilmetodo calcolaSomma(...). Loggetto eugenio istanza di Studente, quindiverr richiamato il metodo di tale classe ed il risulato sar 4.

    Supponiamo adesso di modificare il tipo di eugenio in Persona (non ci preoc-cupiamo del dettaglio del linguaggio, vedremo in 4.3 come possibile farlo inJava): cambiare il tipo di un oggetto, istanza di una classe derivata, in tipo del-la classe base possibile ed proprio per questo motivo che necessario ilpolimorfismo; tuttavia questa conversione o castcomporta una perdita di propri-et delloggetto perch una classe base ha meno informazioni (metodi ed attributi)della classe derivata.A questo punto richiamiamo il metodo calcolaSomma(...) sulloggetto eugenio.Stavolta verr richiamato il metodo della classe base: il tipo di eugenio Personae quindi il risultato 5!Ma come possibile invocare un metodo sullo stesso oggetto in base al suo tipo?Ovviamente questo non pu essere fatto durante la compilazione del program-ma, perch il metodo da invocare deve dipendere dal tipo delloggetto durante

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    28/103

    2 LE IDEE FONDAMENTALI 28

    lesecuzione del programma! Per rendere possibile questo il compilatore devefornire il binding dinamico, cio il compilatore non genera il codice per chia-mare un metodo durante la compilazione (binding statico), ma genera il codiceper calcolare quale metodo chiamare su un oggetto in base alle informazioni sultipo delloggetto stesso durante lesecuzione (run-time) del programma. Questomeccanismo rende possibile il polimorfismo puro (o per sottotipo): il messag-gio che stato inviato alloggetto eugenio era lo stesso, per ci che cambiavaera la selezione del metodo corretto da invocare che dipendeva quindi dal tipo arun-time delloggetto.Ecco come viene invocato correttamente un metodo in una gerarchia di ered-itariet (supponiamo che il metodo venga richiamato su una sottoclasse, p.e.Studente):

    la sottoclasse controlla se ha un tale metodo; in caso affermativo lo usa,altrimenti:

    la classe padre si assume la responsabilit e cerca il metodo. Se lo trovalo usa, altrimenti sar la sua classe padre a predendere la responsabilit digestirlo.

    Questa catena si interrompe se il metodo viene trovato, e sar tale classe ad in-vocarlo, altrimenti, se non viene trovato, il compilatore segnala lerrore in fase dicompilazione. Pertanto lo stesso metodo pu esistere su pi livelli della gerarchiadi ereditariet.Il polimofismo puro non lunica forma di polimorfismo:

    polimorfismo ad hoc (overloading) un metodo pu avere lo stesso nome ma pa-rametri diversi: il compilatore sceglie la versione corretta del metodo inbase al numero ed al tipo dei parametri. Il tipo di ritorno non viene usatoper la risoluzione, cio se si ha un metodo con gli stessi argomenti e diversotipo di ritorno, il compilatore segnala un errore durante la compilazione.Tale meccanismo quindi risolto a tempo di compilazione.N.B. Il polimorfismo puro invece si applica a metodi con lo stesso nome,numero e tipo di parametri e tipo di ritorno e viene risolto a run-time.

    polimorfismo parametrico la capacit di eseguire delle operazioni su un qual-siasi tipo: questa tipologia non esiste in Java (ma pu essere simulatocfr. 3.9), perch necessita del supporto di classi parametriche. Per larealizzazione di questo meccanismo in C++ cfr. [2].

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    29/103

    29

    Parte II

    La OOP in JavaIn questa parte vedremo come vengono realizzati i concetti della OOP in Java.

    3 Classi e oggetti

    3.1 Definire una classe

    La definizione di una classe in Java avviene tramite la parola chiave class seguitadal nome della classe. Affinch una classe sia visibile ad altre classi e quindiistanziabile necessario definirla public:

    public class Prima

    {

    }

    N.B. In Java ogni classe deriva dalla classe base cosmica Object: quindi anche senon lo scriviamo esplicitamente, il compilatore si occupa di stabilire la relazionedi ereditariet fra la nostra classe e la classe Object! Le parentesi { e } individ-uano linzio e la fine della classe ed, in generale, un blocco di istruzioni. bene usare la lettera maiuscola iniziale per il nome della classe; inoltre il nomedella classe deve essere lo stesso del nome del file fisico, cio in questo casoavremmo Prima.java (vedere la sezione 5). Affinch una classe realizzi un ADT(cfr. sezione 2.3) necessario definire i dati e le operazioni.

    3.2 Garantire lincapsulamento: metodi pubblici e attributi pri-vati

    Come si detto (cfr. sezione 2.4), uno dei princpi della OOP lincapsulamen-to: quindi necessario definire dati (membri nella terminologia Java) privati e leoperazioni (detti anche metodi in Java) pubbliche.Definiamo lADT Persona della sezione 2.3 in Java; per adesso supponiamo chela persona abbia tre attributi nome, cognome, anni e due metodi creaPerso-na(...) e stampaDati(...):

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    30/103

    3 CLASSI E OGGETTI 30

    public class Persona

    {

    /* questo metodo inizializza gli attributi nome,

    cognome ed anni

    */

    public void creaPersona(String n,String c,int a)

    {

    nome = n;

    cognome = c;

    anni = a;

    }

    // questo metodo stampa gli attributi

    public void stampaDati()

    {

    System.out.println("Nome: "+nome);

    System.out.println("Cognome: "+cognome);

    System.out.println("Et: "+anni);}

    // attributi

    private String nome;

    private String cognome;

    private int anni;

    }

    Abbiamo definito quindi gli attributi private ed i metodi public: lincapsulamen-

    to garantito!Riflettiamo un attimo sulla sintassi:

    attributi: la dichiarazione di un attributo richiede il modificatore di accesso(usare sempre private!), il tipo dellattributo (String, int, etc. che puessere sia un tipo primitivo che una classe - vedere la sezione 5 per i tipiprimitivi del linguaggio) ed il nome dellattibuto (anni, nome, etc.);

    metodi: la dichiarazione di un metodo richiede invece: il modificatore di ac-cesso (pu essere sia public che private, in questo caso per il metodonon potr essere invocato da un oggetto - bene usarlo per funzioni di

    servizio), il tipo di ritorno che pu essere: o un tipo primitivo o unaclasse o void: cio il metodo non restituisce alcuna informazione. Se il

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    31/103

    3 CLASSI E OGGETTI 31

    tipo di ritorno diverso da void, deve essere usata listruzione return val-ore_da_restituire; come ultima istruzione del metodo; il valore_da_resti-tuire deve avere un tipo in match col tipo di ritorno (devono essere glistessi tipi). Segue quindi il nome del metodo e fra parentesi tonde si speci-ficano gli argomenti (anche detti firma del metodo): anche essi avrannoun tipo (primitivo o una classe) ed un nome; pi argomenti vanno separatida una virgola. La lista degli argomenti pu essere vuota.Nel nostro caso gli argomenti passati al metodo creaPersona(...) ser-vono per inizializzare gli attributi: con lassegnamento nome = n; stiamodicendo che allattributo nome stiamo assegnandogli la variabile n.

    // viene usato per i commenti su una singola linea, mentre /* e */ vengono usatiper scrivere commenti su pi linee (il compilatore ignora i commenti).Il metodo println(...) della classe System usato per scrivere loutput a videoe + serve per concatenare stringhe (vedere la sezione 5).La classe, cos come stata definita, non serve ancora a molto: vogliamo creareoggetti che siano istanze di questa classe, sui quali possiamo invocare dei meto-di. Dove andremo ad istanziare un generico oggetto di tipo Persona? Prima

    di rispondere a questa domanda affrontiamo un altro discorso importante che ciservir per capire alcune cose:

    3.3 Metodi ed attributi statici

    Gli attributi static sono utili quando necessario condividerli fra pi oggetti,quindi anzich avere pi copie di un attributo che dovr essere lo stesso per tuttigli oggetti istanza della stessa classe, esso viene inzializzato una volta per tuttee posto nella memoria statica. Un simile attributo avr la stessa vita del pro-gramma, per esempio possiamo immaginare che in una classe Data utile averememorizzato un array (cfr. 5) dei mesi dellanno:

    private static String[] mesi = {"Gen","Feb","Mar",

    "Apr","Mag","Giu",

    "Lug","Ago","Set",

    "Ott","Nov","Dic"};

    Tale array sar condiviso fra tutti gli oggetti di tipo Data.Siccome tale array, in realt costante, risulta comodo definirlo tale: in Java siusa la parola final per definire un attributo costante:

    private static final String[] mesi = {"Gen","Feb","Mar",

    "Apr","Mag","Giu",

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    32/103

    3 CLASSI E OGGETTI 32

    "Lug","Ago","Set",

    "Ott","Nov","Dic"};

    Quindi mesi non modificabile!Allo stesso modo possibile definire un metodo static: un tale metodo pu es-sere richiamato senza la necessit di istanziare la classe (vedere la sottosezione3.6.2 per un esempio).In Java esiste un punto di inizio per ogni programma, dove poter creare logget-

    to istanza della classe ed invocare i metodi: il metodo main(...). Esso vienerichiamato prima che qualsiasi oggetto stato istanziato, pertanto necessarioche sia un metodo statico. La sua dichiarazione, che deve comparire in una sola

    classe, la seguente:

    public static void main(String args[])

    {

    }

    Quindi public per poter essere visto allesterno, static per il motivoche si dice-va prima, non ha alcun tipo di ritorno, accetta degli argomenti di tipo String

    che possono essere passati a linea di comando.

    3.4 Costruire un oggetto

    Possiamo adesso affrontare la costruzione di un oggetto.In Java un oggetto viene costruito con il seguente assegnamento:

    Prova primo = new Prova();

    Analizziamo la sintassi: stiamo dicendo che il nostro oggetto di nome primo una istanza della classe Prova e che lo stiamo costruendo, con loperatore new,

    attraverso il costruttore Prova().Loggetto che viene cos creato posto nella memoria heap (o memoria dinami-ca), la quale cresce e dimunisce a run-time, ogni volta che un oggetto creato edistrutto.N.B. Mentre la costruzione la controlliamo noi direttamente, la distruzione vienegestita automaticamente dalla JVM: quando un oggetto non viene pi usato, laJVM si assume la responsabilit di eliminarlo, senza che noi ce ne possiamo ac-corgere, tramite il meccanismo di Garbage Collection!Lassegnamento dice che la variabile oggetto primo un riferimento ad un ogget-to, istanza della classe Prova.

    Il concetto di riferimento importante: molti pensano che Java non abbia i punta-tori: sbagliato! Java non ha la sintassi da puntatore ma ne ha il comportamento.

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    33/103

    3 CLASSI E OGGETTI 33

    Infatti una variabile oggetto serve per accedere alloggetto e non per memo-rizzarne le sue informazioni!; pertanto un oggetto di Java si comporta comeuna variabile puntatore di C++. La gestione dei puntatori viene completamentenascosta al programmatore, il quale pu solo usare riferimenti agli oggetti.La situazione dopo la costruzione delloggetto primo la seguente:

    primo

    Prova

    Figura 15: Loggetto primo appena creato

    Sottolineiamo che con la seguente scrittura:

    Prova primo;

    non stato creato alcun oggetto, infatti si sta semplicemente dicendo che loggettoprimo che verr creato sar una istanza di Prova o di una sua sottoclasse; si haquesta situazione:

    primo

    Prova

    Figura 16: Loggetto primo non ancora creato

    cio primo non ancora un oggetto in quanto non fa riferimento a niente!La costruzione dovr avvenire con listruzione:

    primo = new Prova();

    Come si detto prima, il metodo Prova() il costruttore delloggetto, cio il metodo che si occupa di inizializzare gli attributi delloggetto.Essendo un metodo pu essere overloadato, cio pu essere usato con argomentidiversi. Un costruttore privo di argomenti si dice costruttore di default: se nonse ne fornisce nessuno, Java si occupa di crearne uno di default automaticamenteche si occupa di inizializzare gli attributi.Il costruttore ha lo stesso nome della classe e non ha alcun tipo di ritorno.Inoltre esso richiamato soltanto una volta, cio quando loggetto viene creato enon pu essere pi richimato durante la vita delloggetto.

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    34/103

    3 CLASSI E OGGETTI 34

    3.5 La classe Persona e loggetto eugenio

    Vediamo allora come scrivere una versione migliore della classe Persona, in cuiforniamo un costruttore ed un main:

    public class Persona{

    // Costruttore: inizializza gli attributi nome, cognome, anni

    public Persona(String nome,String cognome,int anni){

    this.nome = nome;

    this.cognome = cognome;

    this.anni = anni;

    }

    // questo metodo stampa gli attributi

    public void stampaDati()

    {

    System.out.println("Nome: "+nome);

    System.out.println("Cognome: "+cognome);

    System.out.println("Et: "+anni);

    }

    // attributi

    private String nome;

    private String cognome;

    private int anni;

    // mainpublic static void main(String args[])

    {

    Persona eugenio = new Persona("Eugenio","Polito",26);

    eugenio.stampaDati();

    }

    }

    Commentiamo questa classe: abbiamo definito il costruttore Persona(Stringnome, String cognome, int anni) che si occupa di ricevere in ingresso i treparametri nome, cognome ed anni e si occupa di inizializzare gli attributi nome,cognome e anni con i valori dei parametri. Come si pu notare stata usata

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    35/103

    3 CLASSI E OGGETTI 35

    la parola chiave this: questo non altro che un puntatore che fa riferimen-to alloggetto attuale (o implicito). Quindi la sintassi this.nome significa fairiferimento allattributo nome delloggetto corrente. In questo caso essenzialeperch il nome dellargomento ed il nome dellattributo sono identici. Come ve-dremo, this utile anche per richiamare altri costruttori.Il metodo stampaDati() serve per stampare gli attributi delloggetto.Il metodo main(...) contiene al suo interno due istruzioni:

    Persona eugenio = new Persona("Eugenio","Polito",26); con tale istru-zione stiamo creando loggetto eugenio: esso viene costruito con il costrut-tore che ha la firma (gli argomenti) String,String,int (lunico che ab-biamo definito). A run time la situazione, dopo questo assegnamento, sarla seguente:

    eugenio Persona

    cognome = "Polito"

    nome = "Eugenio"

    anni = 26

    stampaDati()

    Figura 17: Loggetto eugenio dopo la costruzione

    eugenio.stampaDati(); richiama il metodo stampaDati() sulloggetto eu-genio; il . viene usato per accedere al metodo.

    E se avessimo voluto costruire loggetto col costruttore di default? Avremmoottenuto un errore, perch nella classe non sarebbe stato trovato dal compilatorealcun costruttore senza argomenti, quindi bene fornirne uno:

    public class Persona{

    // Costruttore di default

    public Persona()

    {

    this("","",0);

    }

    // Costruttore: inzializza gli attributi nome, cognome, anni

    public Persona(String nome,String cognome,int anni)

    {

    this.nome = nome;

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    36/103

    3 CLASSI E OGGETTI 36

    this.cognome = cognome;

    this.anni = anni;

    }

    // questo metodo stampa gli attributi

    public void stampaDati()

    {

    System.out.println("Nome: "+nome);

    System.out.println("Cognome: "+cognome);

    System.out.println("Et: "+anni);

    }

    // attributi

    private String nome;

    private String cognome;

    private int anni;

    // mainpublic static void main(String args[])

    {

    Persona eugenio = new Persona("Eugenio","Polito",26);

    Persona anonimo = new Persona();

    eugenio.stampaDati();

    anonimo.stampaDati();

    }

    }

    Il costruttore di defaultrichiama il costruttore che ha come argomenti: String,String, int, attraverso il riferimento allargomento implicito this. In questoesempio il costruttore un metodo che usa loverloading: in base al numero etipo di argomenti, il compilatore seleziona la versione corretta del metodo (cfr.Sezione 2.7).Loutput del programma il seguente:

    Nome: Eugenio

    Cognome: Polito

    Et: 26

    Nome:

    Cognome:

    Et: 0

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    37/103

    3 CLASSI E OGGETTI 37

    3.6 Realizzare le relazioni fra classi

    3.6.1 Uso

    Riprendiamo lesempio della sezione 2.6.1: vediamo come si realizza la relazionedi uso. Supponiamo che la classe Persona usi la classe Computer per eseguireil prodotto e la somma di 2 numeri, quindi definiamo la classe Computer e poi laclasse Persona:

    public class Computer

    {

    // restituisce il prodotto di a * b

    public int calcolaProdotto(int a, int b)

    {

    return a*b;

    }

    // restituisce la somma di a + b

    public int calcolaSomma(int a, int b)

    {return a+b;

    }

    }

    Tale classe ha il metodo calcolaProdotto(...) che si occupa di calcolareil prodotto di due numeri, passati come argomento e di restituirne il risultato(return a*b;). Il discorso analogo per il metodo calcolaSomma(...).La classe Persona invece :

    public class Persona

    {

    // Costruttore di default

    public Persona()

    {

    this("","",0);

    }

    // Costruttore: inizializza gli attributi nome, cognome, anni

    public Persona(String nome,String cognome,int anni)

    {

    this.nome = nome;this.cognome = cognome;

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    38/103

    3 CLASSI E OGGETTI 38

    this.anni = anni;

    }

    // questo metodo stampa gli attributi

    public void stampaDati()

    {

    System.out.println("Nome: "+nome);

    System.out.println("Cognome: "+cognome);

    System.out.println("Et: "+anni);

    }

    /* usa loggetto phobos istanza di Computer

    per eseguire il prodotto e la somma degli

    interi a e b passati come argomenti */

    public void usaComputer(int a, int b)

    {

    Computer phobos = new Computer();

    int res = phobos.calcolaProdotto(a,b);

    System.out.println("Risultato del prodotto "+a+" * "+b+": "+res);

    res = phobos.calcolaSomma(a,b);

    System.out.println("Risultato della somma "+a+

    " + "+b+": "+res);

    }

    // attributi

    private String nome;

    private String cognome;

    private int anni;

    // main

    public static void main(String args[])

    {

    Persona eugenio = new Persona("Eugenio","Polito",26);

    eugenio.usaComputer(5,5);

    }

    }

    Il metodo usaComputer(...) crea (quindi usa) un oggetto phobos, istanza dellaclasse Computer (Computer phobos = new Computer();) richiama il metodo

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    39/103

    3 CLASSI E OGGETTI 39

    calcolaProdotto(...) su phobos, passandogli gli argomenti a e b. Il risultatodel calcolo viene posto temporaneamente nella variabile locale res: alluscitadal metodo tale variabile verr eliminata; ogni variabile locale deve essere in-izializzata, altrimenti il compilatore riporta un errore!L istruzione successiva System.out.println(...) stampa loutput a video.res = phobos.calcolaSomma(a,b); richiama sulloggetto phobos il metodocalcolaSomma(...) ed il risultato viene posto in res (tale variabile statagi dichiarata quindi non si deve specificare di nuovo il tipo, inoltre il risulta-to del prodotto viene perso perch adesso res contiene il valore della somma!).Listruzione successiva stampa il risultato della somma.Notiamo che cos come la variabile locale res nasce, vive e muore in questometodo, anche loggetto phobos ha lo stesso ciclo di vita: quando il metodo ter-mina, loggetto phobos viene distrutto automaticamente dal Garbage Collectordella JVMe la memoria da lui occupata viene liberata.N.B. Gli oggetti costruiti nel main (cos come le variabili) vivono per tutta ladurata del programma!Nel main viene creato loggetto eugenio che invoca il metodo usaComputer(...)per usare il computer.

    3.6.2 Metodi static: un esempio

    Riprendiamo la classe Computer: come possiamo notare, non ha degli attribu-ti; in realt, non ci importa istanziare tale classe perch, cos come stata defini-ta, funge pi da contenitore di metodi che da classe istanziabile. Pertanto i metodidi tale classe li possiamo definire static:

    public class Computer{

    // restituisce il prodotto di a * b

    public static int calcolaProdotto(int a, int b){

    return a*b;

    }

    // restituisce la somma di a + b

    public static int calcolaSomma(int a, int b)

    {

    return a+b;

    }

    }

    Adesso dobbiamo rivedere il metodo usaComputer(...) della classe Persona:

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    40/103

    3 CLASSI E OGGETTI 40

    public class Persona

    {

    // Costruttore di default

    public Persona()

    {

    this("","",0);

    }

    // Costruttore: inizializza gli attributi nome, cognome, anni

    public Persona(String nome,String cognome,int anni)

    {

    this.nome = nome;

    this.cognome = cognome;

    this.anni = anni;

    }

    // questo metodo stampa gli attributi

    public void stampaDati()

    {System.out.println("Nome: "+nome);

    System.out.println("Cognome: "+cognome);

    System.out.println("Et: "+anni);

    /* usa i metodi della classe Computer per eseguire

    il prodotto e la somma fra gli interi a e b

    passati come argomenti */

    public void usaComputer(int a, int b)

    {int res = Computer.calcolaProdotto(a,b);

    System.out.println("Risultato del prodotto "+a+

    " * "+b+": "+res);

    res = Computer.calcolaSomma(a,b);

    System.out.println("Risultato della somma "+a+

    " + "+b+": "+res);

    }

    // attributi

    private String nome;

    private String cognome;

    private int anni;

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    41/103

    3 CLASSI E OGGETTI 41

    // main

    public static void main(String args[])

    {

    Persona eugenio = new Persona("Eugenio","Polito",26);

    eugenio.usaComputer(5,5);

    }

    }

    Come si pu notare nel metodo usaComputer(...), questa volta non viene creatoun oggetto istanza della classe Computer, ma si usa questultima per accedereai metodi calcolaSomma(...) e calcolaProdotto(...) , essendo dei metodistatic.

    3.6.3 Aggregazione

    Riprendiamo lesempio discusso nella sezione 2.6.2: si diceva che la classe Personaaggrega la classe Data, perch ogni persona ha una data di nascita.Definiamo la classe Data:

    public class Data {/* Costruttore: inizializza gli attributi giorno,

    mese, anno con i valori passati come

    argomenti */

    public Data(int giorno, int mese, int anno)

    {

    this.giorno = giorno;

    this.mese = mese;

    this.anno = anno;

    }

    // stampa la Data

    public void stampaData()

    {

    System.out.println(giorno+"/"+mese+"/"+anno);

    }

    // attributi

    private int giorno, mese, anno;

    }

    Tale classe ha gli attributi giorno, mese e anno che vengono inizializzati colcostruttore e possono essere stampati a video col metodo stampaData().La classe Persona:

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    42/103

    3 CLASSI E OGGETTI 42

    public class Persona {

    /* Costruttore: inizializza gli attributi nome, cognome,

    e data di nascita */

    public Persona(String nome,

    String cognome,

    int giorno,

    int mese,

    int anno)

    {

    this.nome = nome;

    this.cognome = cognome;

    dataDiNascita = new Data(giorno,mese,anno);

    }

    /* stampa gli attributi e richiama il metodo

    stampaData() sulloggetto dataDiNascita

    per la stampa della data di nascita */

    public void stampaDati()

    {System.out.println("Nome: "+nome);

    System.out.println("Cognome: "+cognome);

    System.out.print("Nato il: ");

    dataDiNascita.stampaData();

    }

    // attributi

    private String nome;

    private String cognome;

    private Data dataDiNascita;

    // main

    public static void main(String args[])

    {

    Persona eugenio = new Persona("Eugenio","Polito",31,12,1976);

    eugenio.stampaDati();

    }

    }

    contiene gli attributi nome, cognome e dataDiNascita (istanza di Data): quindilaggregazione si realizza in Java come attributo.Notiamo che loggetto dataDiNascita viene creato nel costruttore con gli argo-

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    43/103

    3 CLASSI E OGGETTI 43

    menti passati come parametri: loggetto viene costruito solo quando si sa comefarlo.Osserviamo che lincapsulamento garantito: gli attributi delloggetto dataDi-Nascita possono essere letti solo col metodo stampaData().N.B. Come si detto il main deve comparire una sola volta in una sola classe;per chiarezza, quando si ha pi di una classe, consigliabile porlo in unaltraclasse. Quindi, in questo caso, lo togliamo dalla classe Persona e lo poniamo inuna nuova classe, diciamo Applicazione:

    public class Persona {

    /* Costruttore: inizializza gli attributi nome, cognome,

    e data di nascita */

    public Persona(String nome,

    String cognome,

    int giorno,

    int mese,

    int anno)

    {

    this.nome = nome;this.cognome = cognome;

    dataDiNascita = new Data(giorno,mese,anno);

    }

    /* stampa gli attributi e richiama il metodo

    stampaData() sulloggetto dataDiNascita

    per la stampa della data di nascita */

    public void stampaDati()

    {

    System.out.println("Nome: "+nome);

    System.out.println("Cognome: "+cognome);

    System.out.print("Nato il: ");

    dataDiNascita.stampaData();

    }

    // attributi

    private String nome;

    private String cognome;

    private Data dataDiNascita;

    }

    e la classe Applicazione conterr il main:public class Applicazione {

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    44/103

    3 CLASSI E OGGETTI 44

    // main

    public static void main(String args[])

    {

    Persona eugenio = new Persona("Eugenio","Polito",31,12,1976);

    eugenio.stampaDati();

    }

    }

    In seguito verr utilizzato questo modo di procedere.

    3.6.4 Ereditariet

    Vogliamo estendere la classe Persona in modo da gestire la classe Studente,cio vogliamo che Studente erediti da Persona: questo logicamente vero dalmomento che ogni Studente una Persona.Definiamo la classe Persona:

    import java.util.Random;

    public class Persona{

    /* Costruttore: inizializza gli attributi nome, cognome,

    e data di nascita */

    public Persona(String nome,

    String cognome,

    int giorno,

    int mese,

    int anno)

    {

    this.nome = nome;this.cognome = cognome;

    dataDiNascita = new Data(giorno,mese,anno);

    }

    /* stampa gli attributi e richiama il metodo

    stampaData() sulloggetto dataDiNascita

    per la stampa della data di nascita */

    public void stampaDati()

    {

    System.out.println("Nome: "+nome);

    System.out.println("Cognome: "+cognome);

    System.out.print("Nato il: ");

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    45/103

    3 CLASSI E OGGETTI 45

    dataDiNascita.stampaData();

    }

    // autoesplicativo

    public void mangia()

    {

    System.out.println("\nMangio con forchetta e coltello\n");

    }

    // stampa casualmente n numeri (magari da giocare al lotto:)

    public void conta(int n)

    {

    System.out.print("Conto: ");

    Random r = new Random();

    for (int i = 0; i < n; i++)

    System.out.print(r.nextInt(n)+"\t");

    System.out.println();

    }

    // attributi

    private String nome;

    private String cognome;

    private Data dataDiNascita;

    }

    Con listruzione import java.util.Random si sta importando la classe Randomche contenuta nel package java.util (per luso dei package vedere la sezione5) e serve per generare dei numeri pseudo-casuali.Il costruttore ed il metodo stampaDati() sono stati gi discussi.Il metodo mangia() stampa a video un messaggio molto eloquente; il simbolo

    n serve per andare a capo.

    Il metodo conta(...) riceve come argomento un intero n, e stampa n numericasuali attraverso un ciclo iterativo (per i cicli vedere 5).Adesso vogliamo definire la classe Studente come sottoclasse di Persona, incui:

    il metodo mangia() viene ereditato;

    il metodo conta(...) viene riscritto;

    il metodo stampaDati() viene esteso. viene aggiunto il metodo faiFilaInSegreteria() ;

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    46/103

    3 CLASSI E OGGETTI 46

    Supponiamo inoltre che la nuova classe abbia lattributo anniDiScuola.La classe Studente dunque:

    public class Studente extends Persona

    {

    /* Costruttore: richiama il costruttore della classe base

    (inializzando gli attributi nome, cognome, dataDiNascita)

    ed inializza il membro anniDiScuola */

    public Studente(String nome,String cognome,

    int giorno,

    int mese,

    int anno,

    int anniDiScuola)

    {

    super(nome,cognome,giorno,mese,anno);

    this.anniDiScuola = anniDiScuola;

    }

    /* Riscrive il metodo omonimo della classe base:

    Stampa i numeri 1,2,...,n */

    public void conta(int n)

    {

    System.out.print("Conto: ");

    for (int i = 1; i

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    47/103

    3 CLASSI E OGGETTI 47

    System.out.println("...Aspetto il mio turno

    in segreteria...");

    }

    // attributo

    private int anniDiScuola;

    }

    In Java lereditariet resa possibile con la parola chiave extends.Il costruttore richiama il costruttore della classe base, che ha la firma String,String, int ,int, int, attraverso laparola chiave super; inoltre inizializza ilmembro anniDiScuola. Notiamo che per costruire gli attributi nome, cognome,dataDiNascita necessario ricorrere al costruttore della classe base perch han-no tutti campo di visibilit (o scope) private.Il metodo conta(...) stato riscritto: ora stampa correttamente i numeri1,2,...,n.Il metodo stampaDati(...) stato esteso: richiama il metodo omonimo dellaclasse base ed in pi stampa lattributo anniDiScuola.

    Infine stato aggiunto il metodo faiFilaInSegreteria che stampa un messag-gio di attesa...Come si detto gli attributi della classe base non sono accessibili alla classederivata perch hanno scope private. Tuttavia possibile consentire solo alleclassi derivate di avere un accesso protetto agli attributi, attraverso il modifica-tore di accesso protected. La classe Persona pu essere pertanto riscritta nelseguente modo:

    import java.util.Random;

    public class Persona{

    // Costruttore di defaultpublic Persona()

    {

    this("","",0,0,0);

    }

    /* Costruttore: inizializza gli attributi nome, cognome,

    anni e data di nascita */

    public Persona(String nome,

    String cognome,

    int giorno,

    int mese,

    int anno)

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    48/103

    3 CLASSI E OGGETTI 48

    {

    this.nome = nome;

    this.cognome = cognome;

    this.dataDiNascita = new Data(giorno,mese,anno);

    }

    /* stampa gli attributi e richiama il metodo

    stampaData() sulloggetto dataDiNascita

    per la stampa della data di nascita */

    public void stampaDati()

    {

    System.out.println("Nome: "+nome);

    System.out.println("Cognome: "+cognome);

    System.out.print("Nato il: ");

    dataDiNascita.stampaData();

    }

    // autoesplicativo

    public void mangia(){

    System.out.println("\nMangio con forchetta e coltello\n");

    }

    // stampa casualmente n numeri (magari da giocare al lotto:)

    public void conta(int n)

    {

    System.out.print("Conto: ");

    Random r = new Random();

    for (int i = 0; i < n; i++)System.out.print(r.nextInt(n)+"\t");

    System.out.println();

    }

    // attributi

    protected String nome;

    protected String cognome;

    protected Data dataDiNascita;

    // main

    public static void main(String args[])

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    49/103

    3 CLASSI E OGGETTI 49

    {

    Persona eugenio = new Persona("Eugenio","Polito",31,12,1976);

    eugenio.stampaDati();

    eugenio.mangia();

    eugenio.conta(5);

    }

    }

    Adesso possiamo avere accesso diretto agli attributi della classe base dalla classederivata Studente:

    public class Studente extends Persona

    {

    /* Costruttore: inizializza gli attributi

    public Studente(String nome,

    String cognome,

    int giorno,

    int mese,

    int anno,int anniDiScuola)

    {

    this.nome = nome;

    this.cognome = cognome;

    this.dataDiNascita = new Data(giorno,mese,anno);

    this.anniDiScuola = anniDiScuola;

    }

    /* Riscrive il metodo omonmio della classe base:

    Stampa i numeri 1,2,...,n */public void conta(int n)

    {

    System.out.print("Conto: ");

    for (int i = 1; i

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    50/103

    3 CLASSI E OGGETTI 50

    {

    super.stampaDati();

    System.out.println("Anni di scuola: "+anniDiScuola);

    }

    /* stampa il messaggio ... */

    public void faiFilaInSegreteria()

    {

    System.out.println("...Aspetto il mio turno in segreteria...");

    }

    // attributo

    private int anniDiScuola;

    }

    Notare come adesso nel costruttore si possa accedere direttamente agli attributidella classe base (this.nome, this.cognome, this.dataDiNascita).Unaltra cosa da osservare che si reso necessario inserire un costruttore di

    default nella classe base perch il costruttore della classe derivata va a cercaresubito il costruttore di default della superclasse e poi inizializza gli attributi!Vediamo una applicazione di esempio:

    public class Applicazione

    {

    public static void main(String args[])

    {

    Persona bill = new Persona("Bill","Cancelli",13,13,1984);

    bill.stampaDati();

    bill.conta(5);

    bill.mangia();Studente tizio = new Studente("Pinco","Pallino",1,1,1970,15);

    tizio.stampaDati();

    tizio.conta(5);

    tizio.mangia();

    tizio.faiFilaInSegreteria();

    }

    }

    Una possibile esecuzione la seguente:Nel main abbiamo creato loggetto bill (istruzione Persona bill = new

    Persona("Bill","Cancelli",13,13,1984); ), il quale invoca i metodi stam-paDati();, conta(5); e mangia();.

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    51/103

    3 CLASSI E OGGETTI 51

    Figura 18: Esecuzione del programma Applicazione.java

    stato quindi creato loggetto tizio come istanza della classe Studente. Richia-ma il metodo stampaDati: come si pu vedere in Figura 18, oltre al nome,cognome e data di nascita viene stampato lattributo anniDiScuola (ricor-diamoci che tale metodo stato esteso, proprio per permettere di stampare taleattributo).Viene poi richiamato il metodo conta(5): siccome tale metodo stato riscritto,stampa a video la sequenza corretta dei numeri 1,2,. . . ,n.

    Loggetto tizio invoca poi il metodo mangia(), che essendo ereditato stampa lostesso messaggio che stato stampato precedentemente dallo stesso metodo invo-cato da bill.Infine tizio invoca il metodo aggiunto nella classe Studente faiFilaInSe-greteria() che stampa un messaggio.Osserviamo che se avessimo invocato faiLaFilaInSegreteria() sulloggettobill avremmo ottenuto un messaggio di errore, perch tale metodo non definitonella classe Persona.

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    52/103

    3 CLASSI E OGGETTI 52

    3.7 Classi astratte

    Nella sezione 2.6.4 abbiamo parlato del concetto di classe astratta: vediamoadesso come si realizza in Java.Come si detto, un Animale pu essere considerato un contenitore di oper-azioni (dal momento che non si sa come definire tali operazioni in generale:come mangia() o comunica() un Animale?) per tutte le classi derivate, comePersona, Cane etc.: cio la classe Animale una classe astratta.

    Supponiamo che tale classe abbia due metodi astratti mangia() e comunica()ed uno concreto dorme(), dal momento che tutti gli animali dormono allo stessomodo:

    public abstract class Animale

    {

    // metodo astratto per mangiare

    public abstract void mangia();

    // metodo astratto per comunicare

    public abstract void comunica();

    // metodo concreto per dormire

    public void dorme()

    {

    System.out.println("Dormo...");

    }

    }

    Quindi una classe astratta definita tale con la keyword abstract: questo tipodi classe pu contenere sia metodi astratti (definiti ovviamente abstract), sia

    metodi concreti.Ogni classe derivata da una classe astratta deve implementare i metodi astrattidella classe base!Per esempio una eventuale classe Cane potrebbe avere questa forma:

    public class Cane extends Animale

    {

    // costruttore

    public Cane(String nome)

    {

    this.nome = nome;

    }

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    53/103

    3 CLASSI E OGGETTI 53

    // implementa il metodo della classe base

    public void comunica()

    {

    System.out.println("Sono "+nome+" e faccio Bau Bau");

    }

    // implementa il metodo della classe base

    public void mangia()

    {

    System.out.println("Mangio con la bocca e le zampe");

    }

    // attributo

    private String nome;

    }

    Pertanto Cane estende la classe Animale: realizza i metodi astratti mangia() ecomunica ed eredita il metodo dorme().

    Analogamente una classe Persona potrebbe essere cos:public class Persona extends Animale

    {

    // costruttore

    public Persona(String nome, String cognome)

    {

    this.nome = nome;

    this.cognome = cognome;

    }

    // implementa il metodo della classe basepublic void comunica()

    {

    System.out.println("...Salve mondo, sono "+nome+" "+cognome);

    }

    // implementa il metodo della classe base

    public void mangia()

    {

    System.out.println("Mangio con forchetta e coltello");

    }

    // estende il metodo della classe base

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    54/103

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    55/103

    3 CLASSI E OGGETTI 55

    Lesecuzione del programma la seguente:

    Figura 19: Esecuzione del programma Applicazione.java

    Nel main viene creato loggetto bill che una istanza della classe Cane: sudi esso viene invocato il metodo comunica() che stampa lattributo nome (ini-zializzato nel costruttore) ed il verso Bau Bau. bill invoca quindi il metodomangia(), che stampa una stringa che ci spiega come il cane riesca a mangiare.Infine viene richiamato su bill il metodo dorme().Allo stesso modo viene creato loggetto george che unistanza di Persona: essoinvoca gli stessi metodi che invoca loggetto bill ed in pi richiama il metodofaiGuerra().

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    56/103

    3 CLASSI E OGGETTI 56

    3.8 Interfacce

    Le interfacce sono un meccanismo proprio di Java che, come vedremo nellasezione successiva, consentono di avere un supporto parziale ma sufficiente perlereditariet multipla.Attraverso una interfaccia si definisce un comportamento comune a classi che fradi loro non sono in relazione. Come si detto, anche una classe astratta definisceun contenitore di metodi per le classi derivate, quindi in questo caso si usa la

    relazione di ereditariet. Quando si parla invece di interfaccia si definiscono imetodi che le classi dovranno implementare, pertanto in una interfaccia non pos-sono esistere metodi concreti!In UML una interfaccia si disegna cos:

    Figura 20: Diagramma UML per interface

    Considerimo, per esempio, i file HTML ed i file bytecode di Java: ovviamenteessi non hanno nulla in comune, se non il fatto di supportare le stesse operazioni,come apri(...), chiudi(...), etc.Vediamo allora come costruire una interfaccia comune di operazioni da usare sudiversi file, per aprirli, determinarne il tipo e chiuderli. Definiamo allora uninterfaccia FileType:

    public interface FileType

    {

    // apre il file

    public void open();

    // verifica se il tipo di file OK

    public boolean fileTypeOk();

    // chiude il file

    public void close();

    }

    Si sta dicendo che linterfaccia FileType (definita con la keyword interface)definisce i tre metodi open(), fileTypeOk(), close() ed ogni classe che vuoleimplementare questa interfaccia deve implementare i metodi in essa definiti.Supponiamo adesso di voler aprire e verificare un file bytecode di Java (per lastruttura dei bytecode Java cfr. [1]):

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    57/103

    3 CLASSI E OGGETTI 57

    import java.io.*;

    public class FileClass implements FileType

    {

    /* Costruttore: inizializza il nome del file

    che si vuole leggere */

    public FileClass(String nome)

    {

    nomeDelFile = nome;

    }

    // apre il file fisico il cui nome nomeDelFile

    public void open()

    {

    try {

    fileClass = new DataInputStream(new

    FileInputStream(nomeDelFile));

    } catch (FileNotFoundException fne) {

    System.out.println("File "+nomeDelFile+" non trovato.");}

    }

    /* verifica se il file un file bytecode di Java:

    legge i primi 4 byte (cio 32 bit = int) e controlla

    se tale intero il numero esadecimale 0xcafebabe,

    cio lheader del file .class */

    public boolean fileTypeOk()

    {

    int cafe = 0;try {

    cafe = fileClass.readInt();

    } catch (IOException ioe) {}

    if ((cafe ^ 0xCAFEBABE) == 0) return true;

    else return false;

    }

    // chiude il file fisico

    public void close()

    {

    try {

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    58/103

    3 CLASSI E OGGETTI 58

    fileClass.close();

    } catch (IOException ioe) {

    System.out.println("Non posso chiudere il file");

    }

    }

    // file fisico

    private DataInputStream fileClass;

    // nome del file

    private String nomeDelFile;

    // main

    public static void main(String args[])

    {

    if (args.length != 0) {

    FileClass myFile = new FileClass(args[0]);

    myFile.open();

    if (myFile.fileTypeOk())System.out.println("Il file "+args[0]+

    " un bytecode Java");

    else System.out.println("Il file "+args[0]+

    " non un file .class!");

    myFile.close();

    }

    else

    System.out.println("uso: java FileClass \"nome del file\"");

    }

    }

    Provare a compilarlo e ad eseguirlo (sintassi: java FileClass nome dovenome un nome di file .class, per esempio provare con: java FileClassFileClass.class. . . )La classe FileClass implementa le operazioni dellinterfaccia attraverso la key-word implements. Quindi, come si vede dal codice, la classe deve implementaretutti i metodi dellinterfaccia.Il costruttore riceve come argomento il nome del file che usa per inizializzarelattributo nomeDelFile.Il metodo open() implementa il metodo omonimo dellinterfaccia FileType:

    quindi tenta di aprire il file come stream di byte e se non trova il file solleva unaeccezione (per i file e le eccezioni cfr. la sezione 5).

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    59/103

    3 CLASSI E OGGETTI 59

    Il metodo fileTypeOk verifica se il file in aperto una bytecode Java: se lheadero intestazione comincia con il numero esadecimale 0xCAFEBABE (0x significa checi che segue un numero in base 16) allora il file un bytecode Java, altrimentinon lo . Notare che per il test si usato loperatore fra bit XOR - in Java , cherestituisce 0 se i bit sono uguali, 1 altrimenti.close chiude lo stream: se non lo trova (. . . magari stato cancellato o sposta-to.. . ) solleva una eccezione.Il main richiama in ordine i tre metodi di cui sopra.Dal momento che un bytecode un file di byte, si sono usate le classi di accessoai file del package java.io.In 5 verr discusso come accedere ai file.

    In UML implements si disegna cos:

    Figura 21: Diagramma UML per implements

    Dunque FileClass implementa linterfaccia FileType.Analogamente se volessimo verificare un file HTML, un ELF di Linux (file esegu-bile) etc., non dobbiamo far altro che scrivere delle classi che implementano leoperazioni dellinterfaccia FileType.Lutilizzo delle interfacce conveniente, almeno per due motivi:

    si separa linterfaccia dallimplementazione;

    si ha una garanzia per non fare errori: si modifica solo limplementazione enon linterfaccia.

  • 7/28/2019 (E-Book Ita) Java _ Introduzione Alla Programmazione Orientata Ad Oggetti in Java

    60/103

    3 CLASSI E OGGETTI 60

    3.9 Ereditariet multipla

    In 2.6.5 si parlato della ereditariet multipla in teoria: realizziamo adessoqualche esempio pratico.Come si detto in 2.6.5 lereditariet multipla ha tre forme, di cui solo due sonosupportate in Java.Vediamo come realizzare il matrimonio fra una classe concreta ed una astrat-ta: poich in Java ogni classe ha un solo padre, non possibile ereditare da due

    o pi classi contemporaneamente; sembrerebbe a prima vista che il matrimonionon possa essere celebrato. In realt possibile farlo, perch una interfaccia una classe astra