Docsity
Docsity

Prepara i tuoi esami
Prepara i tuoi esami

Studia grazie alle numerose risorse presenti su Docsity


Ottieni i punti per scaricare
Ottieni i punti per scaricare

Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium


Guide e consigli
Guide e consigli


Programmazione Object Oriente, Appunti di Programmazione Java

Corso di Programmazione Object Oriented in cui vengono spiegate le basi della programmazione ad oggetti ed il linguaggio Java. Contiene tutti i principi della programmazione Object Oriente e tutta la teoria necessaria per imparare un linguaggio orientato agli oggetti utilizzando Ereditarietà, Liste e tanto altro. Nel Riassunto vi è tutta la teoria necessaria per superare la prova orale.

Tipologia: Appunti

2020/2021

In vendita dal 08/02/2021

giusy-annunziata-4
giusy-annunziata-4 🇮🇹

4.6

(8)

13 documenti

1 / 50

Toggle sidebar

Questa pagina non è visibile nell’anteprima

Non perderti parti importanti!

bg1
Linguaggio Object Oriented
Il linguaggio orientato agli oggetti è composto da Oggetti, classi e Messaggi.
Oggetti : sono dotati di :
- Attributi: es: dimensione, peso, forza, etc.;
- Comportamenti: la palla rimbalza, l’auto accelera, etc.;
Gli oggetti, possono essere definiti, componendo altri oggetti; es. una macchina è
composta da motore, ruote, etc.;
Oggetti di classi diverse devono conoscersi per poter comunicare tra loro;
Gli oggetti non hanno un nome, ma hanno una referenza (espressione).
Classi: è un insieme degli oggetti con lo stesso comportamento;
Una classe determina i metodi legali:
Esempio:“hello”.println() è Errore, mentre è Corretto scrivere “hello”.lenght().
Una classe determina i messaggi cui un oggetto può rispondere, e sono dotate di:
- Interfaccia Pubblica: che specifica cosa si può fare con gli oggetti fi una classe;
- Implementazione Privata: chi usa gli oggetti non si interessa di come sono
implementati, i metodi che invoca su di essi e di come sono definiti i dati interni.
In Java le classi hanno un nome.
Messaggi: Gli oggetti vengono attivati tramite la ricezione di un messaggio; I messaggi
vengono inviati da altri utenti; Per inviare un messaggio è necessario specificare:
- Ricevente
- Messaggio
- Eventuali informazioni aggiuntive
Non tutti i messaggi sono comprensibili da un determinato oggetto.
Ci si riferisce al monitor mediante il riferimento System.out
Esempio: System.out.println(“Benvenuti al Corso”);
Dove System.out è il riferimento al messaggio,
mentre .println(“Benvenuti al Corso”); è il messaggio;
La classe PrintStream modella monitor e stampanti, e per visualizzare sequenze di caratteri
utilizziamo System.out, che è un’istanza della classe PrintStream, e si riferisce ad un oggetto
predefinito.
Java è un linguaggio Object Oriented, utilizzato per realizzare sistemi software facili da
modificare e mantenere, e possiede una ricchissima libreria per lo sviluppo di interfaccia
utente.
A differenza di linguaggi convenzionali, che devono essere ricompilati per una nuova
piattaforma, Java è portabile, il compilatore genera un Bytecode eseguibile per una CPU
virtuale, che viene poi simulata su una CPU reale.
Il Bytecode è un file costituito da una sequenza di caratteri Unicode, che contiene tutte le
informazioni che descrivono le classi, e viene dato alla JVM, che ne legge i contenuti.
I Tools ovvero i Programmi forniti da Java, che sono presenti nella directory Bin, non prevedono
un interfaccia grafica, quindi sono eseguiti dall’interprete dei comandi di Windows, ovvero la
shell o Prompt dei comandi.
Il parametro ClassPath serve per indicare i processi in cui ricercare i file .class.
Il compilatore e la JVM sanno dove trovare i package forniti con Java;
Ogni volta che dobbiamo usare nuovi package, dobbiamo specificare il percorso in cui si
trovano.
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e
pf1f
pf20
pf21
pf22
pf23
pf24
pf25
pf26
pf27
pf28
pf29
pf2a
pf2b
pf2c
pf2d
pf2e
pf2f
pf30
pf31
pf32

Anteprima parziale del testo

Scarica Programmazione Object Oriente e più Appunti in PDF di Programmazione Java solo su Docsity!

Linguaggio Object Oriented

Il linguaggio orientato agli oggetti è composto da Oggetti , classi e Messaggi.  Oggetti : sono dotati di :

- Attributi: es: dimensione, peso, forza, etc.; - Comportamenti: la palla rimbalza, l’auto accelera, etc.; Gli oggetti, possono essere definiti, componendo altri oggetti; es. una macchina è composta da motore, ruote, etc.; Oggetti di classi diverse devono conoscersi per poter comunicare tra loro; Gli oggetti non hanno un nome, ma hanno una referenza ( espressione ).  Classi: è un insieme degli oggetti con lo stesso comportamento; Una classe determina i metodi legali : Esempio : “hello”.println() è Errore, mentre è Corretto scrivere “hello”.lenght(). Una classe determina i messaggi cui un oggetto può rispondere, e sono dotate di: - Interfaccia Pubblica: che specifica cosa si può fare con gli oggetti fi una classe; - Implementazione Privata: chi usa gli oggetti non si interessa di come sono implementati, i metodi che invoca su di essi e di come sono definiti i dati interni. In Java le classi hanno un nome.  Messaggi: Gli oggetti vengono attivati tramite la ricezione di un messaggio; I messaggi vengono inviati da altri utenti; Per inviare un messaggio è necessario specificare: **- Ricevente

  • Messaggio
  • Eventuali informazioni aggiuntive** Non tutti i messaggi sono comprensibili da un determinato oggetto. Ci si riferisce al monitor mediante il riferimento System.out Esempio: System.out.println(“Benvenuti al Corso”); Dove System.out è il riferimento al messaggio, mentre .println(“Benvenuti al Corso”); è il messaggio; La classe PrintStream modella monitor e stampanti, e per visualizzare sequenze di caratteri utilizziamo System.out , che è un’istanza della classe PrintStream, e si riferisce ad un oggetto predefinito. Java è un linguaggio Object Oriented , utilizzato per realizzare sistemi software facili da modificare e mantenere, e possiede una ricchissima libreria per lo sviluppo di interfaccia utente. A differenza di linguaggi convenzionali, che devono essere ricompilati per una nuova piattaforma, Java è portabile , il compilatore genera un Bytecode eseguibile per una CPU virtuale, che viene poi simulata su una CPU reale. Il Bytecode è un file costituito da una sequenza di caratteri Unicode , che contiene tutte le informazioni che descrivono le classi, e viene dato alla JVM, che ne legge i contenuti. I Tools ovvero i Programmi forniti da Java, che sono presenti nella directory Bin, non prevedono un interfaccia grafica, quindi sono eseguiti dall’interprete dei comandi di Windows, ovvero la shell o Prompt dei comandi. Il parametro ClassPath serve per indicare i processi in cui ricercare i file .class. Il compilatore e la JVM sanno dove trovare i package forniti con Java; Ogni volta che dobbiamo usare nuovi package, dobbiamo specificare il percorso in cui si trovano.

Utilizzare Oggetti

In Java dobbiamo ricordare che quando associamo un nome ad una variabile, esso può essere formato da lettere, cifre e solo il carattere underscore ( _ ), tutti gli altri caratteri non sono ammessi, e il nome non può iniziare con lettera Maiuscola o con una cifra; lettere maiuscole e minuscole sono significative e non è consentito usare spazi. Per convenzione le Variabili hanno il nome che iniziano con la lettera minuscola, mentre le Classi hanno il nome che inizia con la lettera maiuscola, e solitamente nei nomi composti, si utilizza la lettera maiuscola per indicare ogni inizio di nuova parola. Esempio: contoCorrente -> Variabile. ContoCorrente -> Classe. Un Oggetto è l’entità di un programma, dotata di tre proprietà caratteristiche:  Stato: le informazioni che sono conservate nell’oggetto; condizione e comportamento dell’oggetto nel futuro; può variare nel tempo per effetto di un’operazione sull’oggetto.  Comportamento: definito dalle operazioni ( metodi )che possono essere eseguiti sull’oggetto. I metodi possono modificare lo stato dell’oggetto.  Identità. Ogni oggetto è un istanza di un Classe che ne determina il tipo; Una classe descrive un insieme di oggetti, caratterizzati dallo stesso insieme di possibili comportamenti (metodi) e possibili stati (variabili di istanza o campi). Il comportamento di un oggetto è attivato dalla ricezione di un messaggio; le classi determinano il comportamento degli oggetti, definendo quali sono i messaggi leciti , che vengono determinati dalle classi tramite la definizione dei metodi. Un messaggio deve specificare:

- Il nome del metodo da invocare (il comportamento desiderato); - Gli eventuali argomenti ( altre informazioni). Esempio: System.out.println(“Benvenuti al Corso”); dove println è il nome del metodo , e (“Benvenuti al Corso”) è l’ Argomento , ovvero il riferimento ad un oggetto di tipo String. La Segantura (o Signatura ) di un metodo è il nome del metodo + la descrizione dell’argomento. Quando in una classe abbiamo metodi differenti, ma con lo stesso nome, abbiamo un Overloading. String è una classe predefinita e modella una qualunque sequenza di caratteri. “Hello”-> Riferimento all’oggetto di tipo String che modella la sequenza di caratteri Hello. Come invochiamo un metodo: oggetto.metodo(“riferimento ad un oggetto – Argomento”); Esempio : river.length(); Eseguiamo il metodo length sull’oggetto river. L’oggetto, fa da Parametro implicito nell’invocazione del metodo, poiché è come passare a length il parametro river.  Parametri Espliciti: Parametri dati in ingresso ad un metodo; Non tutti i metodi hanno parametri espliciti; Esempio: System.out.println(river); -> river è il parametro esplicito; river.length(); -> Non c’è nessun parametro esplicito;  Parametri Impliciti: Il parametro implicito è l’oggetto su cui è invocato il metodo. Esempio: river.length(); -> river è il parametro implicito. Il valore restituito è un risultato che il metodo ha calcolato, e viene passato al metodo chiamante, per essere usato nella computazione di quest’ultimo, oppure come parametro di un messaggio; Esempio: int n = river.length(); -> n conterrà il valore restituito. System.out.println(river.length()); -> il risultato è usato come parametro esplicito di un messaggio.

Realizzare una Classe : Approccio Metodologico

Fase 1 Progettazione dell’interfaccia  Decidere il comportamento che la classe deve fornire.

- Identificare i metodi da fornire.  Stabilire in che modo la classe verrà usata; - Definire l’interfaccia delle classi e i prototipi dei metodi.  Scrivere un programma di esempio che definisce la classe;  Scrivere lo scheletro della classe. - Prototipi e corpi vuoti. Fase 2 Implementazione di una classeMetodo Definizione di un metodo, esempio: public void ridi () {... } dove lo specificatore di accesso indica la visibilità ( scope ) del metodo. public indica che il metodo può essere utilizzato(invocato) anche dai metodi esterni alla classe.  Costruttore Un Costruttore inizializza le variabili di istanza, e il suo nome dev’essere lo stesso della classe. Il corpo è eseguito quando viene creato un nuovo oggetto e le sue istruzioni assegnano valori alle variabili d’istanza. è possibile avere più costruttori, ma essi devono avere lo stesso nome, quindi si tratterà di overloading , ma il compilatore li distinguerà grazie alla loro lista di parametri espliciti. I costruttori e i metodi public di una classe formano l’interfaccia pubblica della classe. - L’identificatore public indica che una classe è utilizzabile anche al di fuori del package di cui fa parte; una classe pubblica dev’essere contenuta in un file avente il suo nome. È opportuno fornire commenti per ogni Classe , Metodo , Parametro Esplicito e Valore Restituito da una funzione. Un programma in Java è composto da una o più classi, per poterlo eseguire bisogna definirlo una classe pubblica che contiene un metodo. Esempio: public static void main (String args[])Variabili D’Istanza Le Variabili d’istanza contengono i dati memorizzati nell’oggetto. L’istanza di una classe è un oggetto della classe. La definizione di una classe specifica le sue variabili d’istanza; ed esse sono composte da specificatore d’accesso, dal tipo e da nome; Lo Specificatore di accesso indica la visibilità ( scope ) della variabile, se è private significa che la variabile può essere letta e modificata solo dai metodi della classe. è possibile accedere alle variabili private della classe solo attraverso dei metodi public , poiché solo raramente le variabili vengono di chiarate public. Una variabile d’istanza può avere come tipo: - Una classe, esempio String ; - Un Array; - Un tipo primitivo, esempio int ; le istruzioni per inizializzare le variabili sono contenute nel costruttore.

Testare una Classe Classe Tester : è una classe con il metodo main , che contiene le istruzioni per testare un’altra classe. Solitamente consiste in :

1. Costruire uno o più oggetti della classe da testare; 2. Invocare sugli oggetti uno o più metodi; 3. Stampare a video i risultati delle computazioni.  Categorie di Variabili Variabili D’istanza: - Appartengono all’oggetto; - Esistono fin che l’oggetto esiste; - Hanno un valore iniziale di default. Variabili Locali: - Appartengono al metodo; - Vengono create all’attivazione del metodo e cessano di esistere con esso; - Non hanno valore iniziale se non vengono inizializzate. Parametri Formali: - Appartengono al metodo; - Vengono create all’attivazione del metodo e cessano di esistere con esso; - Il valore iniziale corrisponde al valore del parametro reale al momento dell’invocazione. L’ordine della dichiarazione è irrilevante, ma è buona norma dichiarare prima i metodi e poi le variabili d’istanza. Public consente l’accesso alle variabili anche al di fuori della classe mentre private limita l’accesso ai membri della classe. Un parametro Implicito è l’oggetto di invocazione e viene denotato dal riferimento this. La progettazione ad oggetti è caratterizzata attraverso le Classi delle Entità ( Oggetti ) coinvolte nei problemi da risolvere ( individuazione delle classi ): - Individuazione delle classi e delle responsabilità (operazioni)di esse; - Individuazioni delle relazioni tra le classi. Si hanno così i concetti di : - Dipendenza: Usa oggetti delle altre classi; - Aggregazione: Contiene gli oggetti di altre classi; - Ereditarietà: Relazione sottoclasse/Superclasse. In breve possiamo dire che per Realizzare una Classe: 1. Individuare i metodi dell’interfaccia pubblica, che determinano le operazioni che si vogliono eseguire su un oggetto della classe; 2. Individuare le variabili d’istanza, che determinano i dati da utilizzare; 3. Individuare il Costruttore; 4. Codificare i metodi; 5. Collaudare la classe tramite una classe Tester/Main.

Conversioni Le conversioni possono avvenire in tre diversi modi:  Conversioni : avviene durante un’operazione di assegnamento; Quando un valore di un tipo viene assegnato ad una variabile di un altro tipo; è consentita solo se in maniera crescente.  Promozione : Avviene in un’espressione aritmetica, automaticamente quando gli operatori aritmetici devono convertire gli operandi.  Casting : è la tecnica di conversione più pericolosa e potente; Tramite un casting esplicito si possono realizzare sia e conversioni larghe che quelle strette. Una variabile può essere dichiarata ovunque nel codice, e la dichiarazione inizia con uno specificatore d’accesso. La variabile Final , è una variabile costante , il loro valore non può essere modificato; può essere dichiarato nel

- Metodo : final nomeTipo nomeVariabile = espressione - Classe : specificatoreDiAccesso static final nomeTipo nomeVariabile = es. Solitamente queste variabili vengono identificate con nomi scritti in Maiuscolo. L’utilizzo di static denota una variabile dalla classe, quindi non viene creata una copia per ogni oggetto istanziato, ma tutti gli oggetti fanno riferimento alla stessa variabile. Classe Math La classe Math del package java.lang contiene una serie di metodi statici da utilizzare per caricare funzioni matematiche su tipi di dati primitivi. Questo metodo lavora su double e restituiscono double , ma non è un limite, poiché funziona anche su tutti gli altri tipi, tranne sui boolean. Non è associata ad un oggetto, ma alla classe stessa, quindi non opera su un’istanza; possono essere invocate senza alcun riferimento ad un oggetto, e sono definite con l’aggiunta del prefisso Static. Sono invocate utilizzando il nome della classe , pertanto NON necessitano del this. (riferimento), e non possono accedere a variabili d’istanza e metodi non statici, ma possono invocare il costruttore. Il metodo statico non opera su un particolare oggetto della classe, poiché non ha il parametro implicito. Esempio: NomeClasse.NomeMetodo(Parametri)

Decisioni e Iterazioni

L’istruzione if viene utilizzata per esprimere una decisione ed è strutturata: if(condizione) { comando } Essa è composta da una condizione e dall’istruzione da eseguire qual ora la condizione viene verificata. Una versione più articolata del if è if /else che è strutturato: if (condizione) istruzione else istruzione Riferimento Null Il riferimento NULL non si riferisce ad alcun oggetto, e per verificare se un oggetto è null si usa l’operatore ==. Occasionalmente vorremmo restituire un indicatore che specifichi che non è possibile restituire alcun oggetto, in tale situazione situazione usiamo il valore Null. Condizioni Multiple Molto spesso ci troviamo a dover utilizzare cascate di if/else poiché abbiamo molte condizioni da confrontare, e in questo caso bisogna stare molto attenti alla struttura del programma. Un’alternativa a tutti questi if/else sarebbe lo switch , che utilizza la struttura:

switch(x) { case value1 : statement1; break; case value2 : statment2; break; default : statment n ; break; } x viene confrontata con tutti i valori, nel caso di successo si esce nell’istruzione corrispondente, altrimenti esce nella condizione di default, presenta varie regole:

- I valori dei case possono essere costanti o costanti letterali intere; - Ad ogni caso è associata una sequenza di istruzioni; - Ogni caso deve terminare con break. È consigliabile al posto di una cascata If/else, poiché Java al rilevamento di un else lo associa all’ultimo if non associato ad un else, solitamente si utilizzano le parentesi per forzare le associazioni. Precedenze di Operatori Logici Java utilizza vari operatori logici, ma vi è un ordine di priorità tra essi : -! ha la priorità più alta; - && segue! ; - || ha la priorità più bassa. Ovviamente possiamo utilizzare le parentesi () per forzare le operazioni e aumentare la priorità. Iterazioni Java fornisce vari metodi iterativi, tra essi troviamo: - Ciclo while , finche la condizione è vera, esegui le istruzioni; Strutturato con : while( condizione ) { istruzioni } - Ciclo do while , a differenza del while, esegue le istruzioni almeno una volta, e arrivato alla fine controlla la condizione; strutturato con : do { istruzioni } while (condizione); - Ciclo for , viene strutturato con : for ( inizializzazione ; condizione ; update ) { istruzioni } N.B. aggiungendo ; dopo la (condizione), otterremo che il contenuto tra le parentesi () si ripeterà fino a che la condizione non sarà soddisfatta. Talvolta per interrompere un ciclo iterativo viene utilizzata l’istruzione break , che interrompe il ciclo prima che la condizione venga soddisfatta; Mentre l’istruzione continue realizza il comando opposto.

Grazie al metodo set , che ha come parametro un indice ed un oggetto, è possibile rimpiazzare un oggetto. Gli indici ammissibili per i metodi che fanno riferimento ad oggetti memorizzati sono compresi tra 0 e size -1; mentre quelli che vengono utilizzati per metodi che inseriscono nuove posizioni sono compresi tra 0 e size. Se si specifica un indice all’infuori di questo range viene generata un eccezione Runtime. A partire da Java 5.0, la conversione tra i tipi primitivi e le corrispondenti classi wrapper è automatica ed è detta Auto-Boxing , e possono avvenire anche all’interno delle espressioni.

Progettazione delle classi

Scelta delle classi Per scrivere una buona applicazione usando un linguaggio ad oggetti come Java è bene fare un’adeguata progettazione iniziale. Il punto focale su cui concentrarsi sono le classi.  Nella programmazione funzionale classica ci si concentra sulle funzioni: sul flusso che il codice dovrebbe seguire.  Nella programmazione ad oggetti invece l’accento è sulle entità, cioè gli oggetti appartenenti alle varie classi individuate ¡ I metodi, cioè la parte funzionale, devono essere pensati come associati alle entità Una classe rappresenta un singolo concetto del dominio dell’applicazione. Può rappresentare:

- Un concetto matematico (come la classe Rettangle); - Un’astrazione di un'entità della vita reale (come il concetto di Bank Account). Scegliere una classe Esistono vari tipi di classi, in base cosa fanno: - Una classe può svolgere un lavoro: classi di questo tipo vengono dette classi Attori e in genere hanno nomi che terminano con “er” o “or” Scanner Random (meglio se RandomNumberGenerator) - Classi di utilità che non servono a creare oggetti ma forniscono una collezione di metodi statici e costanti Math - Classi starter , che in genere contengono il solo metodo main e hanno il solo scopo di avviare la computazione (classi test) Scelta delle classi Sono sintomi di errori di progettazione possono essere di vario tipo, per esempio se dal nome di una classe non si capisce cosa dovrebbero fare gli oggetti della classe stessa, oppure se il nome di una classe non rappresenta un gruppo di entità, ma una specifica funzione. Sono due i criteri utili per analizzare la qualità di una interfaccia pubblica di una classe:  Coesione Una classe deve rappresentare un singolo concetto, l’interfaccia contiene solo operazioni tipiche del concetto che la classe realizza Esempio: la classe Purse manca di coesione La classe Purse esprime due concetti: o La borsa che contiene monete e calcola il loro valore totale o Il valore delle singole monete Soluzione: Si usano due classi: public class Coin { public Coin(double aValue,String aName){...} public double getValue(){...} }

public class Purse { public Purse(){...} public void add(Coin aCoin){...} public double getTotal(){...} } Una classe con bassa coesione fa tante cose insieme, svolgendo molto lavoro "sparso" e non correlato (ha troppe responsabilità). Questo tipo di situazione sarebbe da evitare in quanto queste classi risultano: o complesse da riutilizzare (bassa riusabilità); o complicate da manutenere (scarsa manutenibilità); o delicate e critiche in quanto soggette a continui cambiamenti (bassa flessibilità) Una forma comune di bassa coesione si ha in quelle classi che presentano un grandissimo numero di metodi (pubblici o privati).  Accoppiamento Una classe A dipende da una classe B se usa esemplari di B (oggetti o metodi di B) Esempio: Purse dipende da Coin perché usa un’istanza di Coin, mentre Coin non dipende da Purse. È possibile avere molte classi che dipendono tra di loro (accoppiamento elevato) I problemi dell’accoppiamento elevato sono: o Se una classe viene modificata tutte le classi che dipendono da essa potrebbero necessitare di una modifica o Se si vuole usare una classe in un altro programma bisognerebbe usare anche tutte le classi da cui quella classe dipende. Accoppiamento elevato e accoppiamento basso Supponete di avere una classe Videoteca per gestire il noleggio di video musicali da parte dei clienti di una videoteca, che abbia variabili istanza : codiceCliente, nomeCantante, creditoCliente, listaVideoNoleggiati, titoloVideo, n_canzoniCantante, n_copieDisponibili e che abbia metodi che consentono di visualizzare ciascuno dei dati, e metodi per modificare, rispettivamente, il numero di copie disponibili, il numero di canzoni di ciascun cantante e il credito di ciascun cliente. La classe Videoteca, così come pensata, ha una bassissima coesione, poiché preposta a modellare entità distinte (il cliente, il video noleggiato e il relativo cantante). Per migliorare la progettazione, dobbiamo separare le diverse entità che entrano in gioco, definendo per esse classi separate e opportunamente accoppiate. Una possibile soluzione è offerta dal seguente schema: Videoteca – Cliente – Video – Cantante. La classe Videoteca gestisce il noleggio di un video da parte di un cliente per un dato numero di giorni. La classe Cliente crea un cliente con un credito iniziale e ha metodi per aggiornare il credito e la lista dei video noleggiati, aggiungendo il titolo di un nuovo video a tale lista. La classe Video crea un video con un certo numero di copie iniziali e ha metodi per aggiornare tale numero La classe Cantante crea un cantante con nome e numero di canzoni inizialmente inserite nel database e ha un metodo per incrementare tale numero. Tutte le classi (tranne Videoteca, che è la principale) hanno metodi per reperire i dati privati. Effetti collaterali Gli effetti collaterali possono introdurre dipendenze e possono causare comportamenti inattesi. E’ buona regola ridurre al minimo gli effetti collaterali. Scambio per valore e scambio per riferimentoScambio per valore : il parametro è copiato all’atto dell’invocazione (variabili indipendenti). Java consente solo questo tipo di scambio.

 Può contenere metodi non dichiarati nell’interfaccia. Sintassi interfaccia: Sintassi classe che implementa l’interfaccia: public interface InterfaceName public class ClasseName implements InterfaceName… { { method signatures method e instance variables } } In tal modo la classe si impegna al rispetto di un contratto. Una classe può implementare anche più di una interfaccia. In questo caso basta elencare, separate da virgola, tutte le interfacce che implementa dopo la parola riservata implements. I metodi della classe che corrispondono a quelli dell’interfaccia implementata devono obbligatoriamente essere dichiarati public. Un’interfaccia va definita in un file .java che si chiama con lo stesso nome dell’interfaccia(esattamente come le classi pubbliche). Conversione fra tipi È possibile convertire dal tipo di una classe al tipo dell’interfaccia implementata dalla classe. Ovviamente non è possibile convertire dal tipo di una classe al tipo di un’interfaccia che NON è implementata da quella classe. Per convertire un tipo interfaccia in un tipo classe occorre un casting. E’ possibile effettuare il casting di un oggetto ad un certo tipo solo se l’oggetto in origine era di quel tipo. L’operatore instanceof permette di verificare se un oggetto appartiene ad un determinato tipo. Al fine di evitare il lancio di un’eccezione prima di effettuare un cast di un oggetto ad un certo tipo classe possiamo verificare se l’oggetto appartiene effettivamente a quel tipo classe. Alcune interfacce standard  L’interfaccia Comparable contiene un metodo astratto chiamato compareTo, usato per confrontare oggetti.  L’interfaccia Iterator indica i metodi da implementare per gestire una collezione di oggetti. Caso per caso si deve decidere l’ordine con cui gli oggetti della collezione devono essere restituiti dai metodi. (boolean hasNext(), Object next(), void remove()). Polimorfismo (Preso da internet) Il termine polimorfismo viene usao in senso generico per riferirsi a espressionii che possono rappresentare valori di diversi tipi(dette espressioni polimorfiche ). Nel contesto della programmazione orientata agli oggetti, si riferisce al fatto che una espressione il cui tipo sia descritto da una classe A può assumere valori di un qualunque tipo descritto da una classe B sottoclasse di A (polimorfismo per inclusione); Polimorfismo vs Overloading Entrambi invocano metodi distinti con lo stesso nome, ma: o Con l’overloading scelta del metodo appropriato avviene in fase di compilazione, esaminando il tipo di parametri. ( early binding , effettuato dal compilatore) o Con il polimorfismo avviene in fase di esecuzione. ( late binding , effettuaro dalla JVM)

Interfacce di smistamento Permettono ad una classe di richiamare un metodo prestabilito per ottenere maggiori informazioni. Classi interne Le classi interne sono classi definite all’interno di altre classi. Fuori dai metodi sono visibili in tutti i metodi, all’interno di un metodo è visibile solo in questo metodo.  I metodi della classe interna hanno accesso alle variabili e ai metodi a cui possono accedere i metodi della classe in cui sono definite (accesso all’ambiente in cui è definita).  Se definite in un metodo statico accedono solo alle variabili statiche non alle variabili di istanza.  Possono accedere a variabili locali solo se sono state dichiarate final.  Una variabile di tipo riferimento ad un oggetto è final quando si riferisce sempre allo stesso oggetto.  Lo stato dell’oggetto può cambiare, ma la variabile non può riferirsi ad un altro oggetto. Oggetti dimostrativi

In molti casi si ha la necessità di testare una classe prima che l’intera applicazione sia stata completata.

Un oggetto di simulazione (mock) fornisce gli stessi servizi di un altro oggetto, ma in maniera semplificata.

Ad esempio, se si vuole testare una classe senza aver a disposizione tutte le funzionalità di un'altra classe, basta dichiarare un tipo interfaccia con gli stessi metodi forniti dalla classe con le funzionalità mancanti. La classe da testare dovrebbe usare solo questa interfaccia e mai la seconda classe che implementa questa interfaccia. E’ necessario che la classe reale e la classe dimostrativa implementino lo stesso tipo di interfaccia in modo tale che non c’è bisogno di cambiare nulla quando si passa dalla classe mock alla classe reale. Questo metodo è vantaggioso quando le classi sono sviluppate da due programmatori diversi e ciò ci permette di non aspettare che la classe dell’altro programmatore venga completata. Eventi di temporizzazione La classe Timer in java.swing genera una sequenza di eventi ad intervalli di tempo prefissati. (Usati per la programmazione di un animazione) Un evento di temporizzazione deve essere notificato ad un ricevitore di eventi. Per creare un ricevitore bisogna definire una classe che implementa l’interfaccia ActionListener in java.awt.event. Un temporizzatore invoca il metodo actionPerformed dell’oggetto listener ad intervalli regolari. Il parametro interval indica il lasso di tempo tra due eventi in millisecondi.

Mettere in ombra variabili di istanza Una sottoclasse non ha accesso alle variabili private della super classe. È un errore comune risolvere il problema creando un’altra variabile di istanza con lo stesso nome. La variabile della sottoclasse però, mette in ombra quella della superclasse. Costruzione di sottoclassi Per invocare il costruttore della superclasse dal costruttore di una sottoclasse uso la parola chiave super seguita dai parametri del costruttore e deve essere il primo comando del costruttore della sottoclasse. Se il costruttore della sottoclasse non chiama il costruttore della superclasse, viene invocato il costruttore predefinito della superclasse. (Posso salvare una variabile della sottoclasse in una superclasse perché essa deriva da quest'ultima. Però non posso usare i metodi della sottoclasse ma solo quelli della superclasse.) Fattorizzazione L’ereditarietà può essere anche usata per spostare un comportamento comune a due o più classi in una singola superclasse. Accedere ai dati delle sottoclassi Un metodo print nella superclasse è capace di visualizzare solo gli elementi comuni della superclasse. Per visualizzare i dati dei singoli oggetti(sottoclassi), dei quali la superclasse non conosce le proprietà, bisogna usare il polimorfismo. Aggiungere un metodo print a ogni sottoclasse e nella superclasse. Classi astratte Un incrocio tra classe ed interfaccia. Ha alcuni metodi normalmente implementati ed altri astratti.

  • Un metodo astratto non ha implementazione. Le classi che estendono una classe astratta sono OBBLIGATE ad implementarne i metodi astratti. Nelle sottoclassi in generale non si è obbligati ad implementare i metodi della superclasse. Attenzione: non si possono creare oggetti di classi astratte poiché ci sono metodi non implementati (come nelle interfacce). È possibile dichiarare astratta una classe priva di metodi astratti, in tal modo evitiamo che possano essere costruiti oggetti di quella classe. In generale, sono astratte le classi di cui non si possono creare esemplari. Le classi non astratte sono dette concrete. Le classi astratte forzano la realizzazione di sottoclassi. Un metodo astratto consente di non scrivere un metodo fittizio che viene poi ereditato dalle sottoclassi. Confronto Classi Astratte – Interfacce  Un’ interfaccia indica solo dei metodi da implementare. o Consente l’uso di “altre classi” per l’abolizione di dati. o Può facilmente essere integrata in un progetto sviluppato indipendentemente. o È consentito implementare più interfacce con la stessa classe.  Una classe astratta fornisce più struttura. o Definisce alcune implementazioni di default. o Permette di definire delle variabili di istanza/statiche/final. o Una classe astratta fornisce una base per le classi che la estenderanno (una classe può estendere una sola superclasse)  Non è errato usare entrambe in un progetto:

o l’interfaccia definisce un supertipo per l’utilizzo di un codice (es. DataSet). o Ciascuna classe astratta è usata per fornire una base alle implementazioni dell’interfaccia. Metodi e classi final Per impedire al programmatore di creare sottoclassi o di sovrascrivere certi metodi, si usa la parola chiave final. Esempio:  public final class String -> Questa classe non si può estendere.  public final boolean checkPassword(...) -> Questo metodo non si può sovrascrivere. Accesso protetto: variabili d’istanza Ai dati protected di un oggetto si può accedere dai metodi della classe, di tutte le sottoclassi, e da tutte le classi che si trovano nello stesso package. Problema: la sottoclasse può avere metodo aggiuntivi che alterano i dati della superclasse. Accesso protetto: metodi Protected può essere usato per forzare l’uso di alcuni metodi solo da oggetti della stessa classe o di una sottoclasse. Si usa in genere per metodi il cui uso corretto dipende dalla conoscenza di dettagli di implementazione. Ereditarietà e specificatori di accesso Quando si sovrascrivono i metodi di una superclasse non se ne può restringere la visibilità. Tabella controllo di accesso a variabili, metodi e classi(Specificatori di accesso): Accessibile da public package private protected Stessa Classe SI SI SI SI Altra Classe (stesso package)

SI SI NO SI

Altra classe non sottoclasse (altro package)

SI NO NO NO

Sottoclasse (altro package)

SI NO NO SI

OBJECT: La classe universale La classe Object è la superclasse di tutte le classi Java. Ogni classe che estende un’altra classe, estende per default la classe Object. Metodi della classe Object:String toString() o Restituisce una rappresentazione dell’oggetto in forma di stringa.  Boolean equals(Object otherObject) o Verifica se l’oggetto è uguale a un altro.  Object clone() o Crea una copia dell’oggetto. È opportuno sovrascrivere questi metodi nelle nostre classi. Sovrascrivere toString Restituisce una stringa contenente lo stato dell’oggetto. Essa è automaticamente invocata quando si concatena una stringa con un oggetto. Questa operazione funziona solo se uno dei due oggetti è già una stringa. Il compilatore può invocare toString() su qualsiasi oggetto, dato che ogni classe estende la classe Object. Se nessuno dei due oggetti è una stringa il compilatore genera un errore. È importante fornire il metodo toString() in tutte le classi! Ci consente di controllare lo stato di un oggetto. Se x è un oggetto e abbiamo sovrascritto toString(), possiamo invocare System.out.println(x). Il metodo println della classe PrintStream invoca x.toString().

Se invochiamo il metodo dobbiamo usare un cast per dire al compilatore che account1.clone() ha lo stesso tipo di accont2. Questo metodo però non funziona nelle sottoclassi. Come soluzione a ciò possiamo invocare il metodo clone della classe Object:  Crea un nuovo oggetto dello stesso tipo dell’oggetto originario.  Copia le variabili di istanza dall’oggetto originario a quello clonato. Però il metodo Object.clone si comporta bene solo se un oggetto contiene: numeri, valori booleani, stringhe. Bisogna usarlo con cautela se l’oggetto contiene riferimenti ad altri oggetti, dato che andrebbero di conseguenza modificati e non gli si può creare un clone dato che verrebbe creata una copia di riferimento all’ oggetto. Quindi è inadeguato per la maggior parte delle classi! Precauzioni dei progettisti di Java:  Il metodo Object.clone è stato dichiarato protetto. Non possiamo invocare x.clone() se non all’interno della classe, di una sottoclasse o dello stesso pacchetto dell’oggetto x.  Una classe che voglia consentire di clonare i suoi oggetti deve implementare l’interfaccia Cloneable, in caso contrario viene lanciata un’eccezione di tipo : CloneNotSupportedException. Tale accezione va catturata anche se la classe implementa Cloneable. In genere, quando sovrascriviamo clone lo ridefiniamo public così è possibile usarlo dovunque. Interfaccia Cloneable Public interface Cloneable{} Interfaccia contrassegno :  Non ha metodi  Usato solo per verificare se un’altra classe la realizza  Se l’oggetto da clonare non è un esemplare di una classe che la realizza viene lanciata l’eccezione. Ereditarietà multipla Una classe più avere più padri di pari livello. In Java non è consentita, per la fragilità del meccanismo. Essa si realizza tramite il concetto di interfaccia. Un problema che potrebbe portare è : l’ ereditarietà a diamante.

Progettazione orientata agli oggetti

Il ciclo di vita del software comprende tutte le attività dall’analisi iniziale fino all’obsolescenza. Un procedimento formale per lo sviluppo del software consiste nel descrivere le varie fasi da compiere e fornire le linee guida su come eseguire le fasi. Le fasi principali del processo di sviluppo sono:  Analisi: Durante la quale si stabilisce cosa deve fare il programma finale e non come lo deve fare. Il suo risultato sarà un documento dei requisiti.  Progettazione: Durante la quale si ha una pianificazione di come implementare il sistema e si scoprono le strutture per la soluzione del problema decidendo i metodi e le classi. Il risultato sarà una descrizione delle classe e dei metodi e dei diagrammi delle relazioni tra classi.  Implementazione: Durante il quale si scrive e compila il codice, quindi si implementano le classi e i metodi scoperti nella fase precedente e il suo risultato sarà appunto il programma.

Collaudo: Durante il quale si esegue il test per vedere il programma funziona correttamente. Il suo risultato è un documento riassuntivo dei test eseguito e dei relativi risultati.  Installazione: Durante la quale gli utente installano ed usano il programma per gli scopi previsti. Determinazione delle classi: Le classi rappresentano insiemi di oggetti con lo stesso comportamento. Entità con occorrenze multiple nella descrizione di un problema sono buoni candidati di oggetti. Determinate cosa hanno in comune e progettate la classe in modo da catturare gli aspetti comuni. Rappresenta alcune entità come oggetti, altre come dati. Non tutte le classi possono essere scoperte nella fase di analisi. Alcune classi possono essere state già realizzate Determinazione dei metodi: Guardare ai verbi nella descrizione dei compiti da eseguire e bisogna stabilire per ogni metodo necessario la classe in cui collocarlo. Schede CRC(Classe, Responsabilità, Collaboratori) Descrive una classe, le sue responsabilità e i suoi collaboratori. Usare una scheda per ogni classe e per ogni metodo, individuare una classe responsabile. Relazioni tra classi:  Ereditarietà: Relazione del tipo “ è un” vista in precedenza.  Associazione/Aggregazione: Relazione del tipo “ ha un”. Gli oggetti di una classe contengono riferimenti ad oggetti di un’altra classe.  Dipendenza: Relazione del tipo “usa”. Associazione è una forma più forte di dipendenza. Per avere dipendenza basta passare un oggetto come parametro di un metodo. Per avere associazione occorre che l’oggetto sia referenziato da una variabile d’istanza. Notazione UML (Per attributo si intende un proprietà dell’oggetto osservabile dall’esterno.) Procedura di sviluppo programma

  1. Collezionare i requisiti;
  2. Utilizzare le schede CRC per classi, responsabilità e collaboratori;
  3. Utilizzare diagrammi UML per registrare le relazioni tra classi;
  4. Utilizzare javadoc per documentare il comportamento dei metodi;
  5. Implementare il programma. Documentazione Si può usare javadoc per generare la documentazione. In prima istanza si può lasciare il corpo dei metodi vuoto. Lanciando javadoc si ottiene una documentazione in formato HTML. Vantaggi: