Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
sviluppo completo, al suo rilascio, alla sua successiva evoluzione, fino al suo ritiro.
Definizione (cosa)
Sviluppo (come)
Manutenzione (modifiche)
FASE DI SVILUPPO
Concetti chiave:
Concetti chiave:
1) Astrazione dei dati (tipo<->classe, definizione dell’insieme dei valori e delle operazioni possibili)
a) Tipo di dato astratto (classe) formato da interfaccia e struttura dati; la struttura dati è
incapsulata nelle operazioni su di essa definite (interfaccia).
b) Oggetto (o istanza) Definizione di Booch
Un oggetto ha uno stato, un comportamento e un’identità:
- Un oggetto aha dati interni (il suo stato);
- Metodi (per implementare un comportamento);
- Ogni oggetto è unico (ha un proprio spazio di indirizzamento in memoria);
2) Tecniche di programmazione ad oggetti: con oggetti, basata sugli oggetti, orientata agli oggetti
3) Vantaggi OOP:
a) Modularità: le classi sono i moduli del sistema software
b) Coesione dei moduli: una classe è un componente software ben coeso in quanto
rappresentazione di un’unica entità
c) Disaccoppiamento dei moduli: in quanto i metodi operano sulla struttura dati interna ad
un oggetto
d) Information hiding: sia le strutture dati che gli algoritmi possono essere nascosti alla
visibilità dall’esterno di un oggetto
e) Riuso: l’ereditarietà consente di riusare la definizione di una classe nel definire nuove
(sotto)classi; inoltre è possibile costruire librerie di classi raggruppate per tipologia di
applicazioni
f) Estensibilità: il polimorfismo agevola l’a ggiunta di nuove funzionalità, minimizzando le
modifiche necessarie al sistema esistente quando si vuole estenderlo
SINTASSI JAVA
Commenti:
1) // singola linea
2) /* */ più linee
3) /** */ di documentazione
Identificatori:
1) Possono iniziare con: lettere, underscore, dollaro, sequenza di caratteri che può contenere numeri
2) C’è distinzione tra maiuscole e minuscole
3) Le parole chiave sono identificatori di significato speciale (già le conosci)
1) Condizionali:
- if, if else
- switch
2) Cicli:
- for
- while, do-while
Operatori:
Caratteri speciali:
1) \n -> a capo (new line)
2) \t -> tabulazione
3) \b -> cancella a sinistra (backspace)
4) \r -> inizio riga (carriage return)
5) \f -> avanzamento pagina (form feed)
6) \\ -> barra inversa
7) \” -> virgolette
8) \’ -> apice
Array:
CLASSI E OGGETTI
1) Classe:
- Ha un nome (deve essere uguale al nome del file che la contiene), il corpo della classe è
racchiuso tra parentesi graffe ed è formato da attributi e metodi.
2) Metodi (o funzioni):
- Un applicazione per essere eseguita deve avere un metodo principale, il main.
- [modifiers] returnType methodName (Argument list)
{ method body }
- I parametri di ingresso vengono sempre passati per valore (degli oggetti viene passato il
riferimento invece).
- Una variabile di un metodo è valida fino a quando non termina il metodo
3) Attributi:
- Indicano lo stato interno di un oggetto.
- [modificatore] Tipo nomeAttributo = [Valore]
- È consigliare usare dei metodi set e get per accedere e scrivere su attributi di una classe per
mantenere un disaccoppiamento tra i moduli.
- Un attributo di un oggetto è valido fino a quando è vivo l’oggetto.
4) Oggetti:
- Istanze di una classe dotate di una loro propria individualità, si differenziano per lo stato
interno.
- Gli oggetti possono interagire tra loro per scambio di messaggi.
5) Modificatori:
- public, private, static, protected.
- Se non ne viene specificato uno il membro è visibile a livello di package.
NOTA SULLE VARIABILI LOCALI: Le variabili locali a un metodo: (1) sono visibili solo dal corpo del metodo,
(2) vengono allocate (nello stack di runtime) alla chiamata e deallocate all’uscita del metodo, (3) non
vengono inizializzate (diversamente dai campi di una classe).
NOTA SULLA STRUTTURA DI UN’APPLICAZIONE: Il sorgente di un’applicazione consiste di uno o più file
(“unità di compilazione”). Ogni file contiene una o più dichiarazioni di classi (o di interfacce), di cui al più
una dichiarata public. Il nome del file deve essere uguale a quello della sua classe public, con estensione
.java
NOTA SULL’OPERATORE = APPLICATO A DUE OGGETTI: Se obj1 e obj2 sono due oggetti diversi e faccio
obj2=obj1 allora entrambi i nomi faranno riferimento allo stesso oggetto.
OVERLOAD: Un nome è overload quando assume più significati. L’overload di un metodo si distingue in
base al tipo e all’ordine di parametri.
COSTRUTTORI: In Java il costruttore viene creato di default se non definito, se invece ne definisco uno
senza parametri l’operatore new utilizza quello da me definito.
Il costruttore deve avere lo stesso nome della classe, non ritorna niente (neanche void), può avere o no dei
parametri, viene richiamato da new che restituisce un riferimento all’oggetto chiamato.
DISTRUTTORI: Gli oggetti vengono creati dinamicamente. Finito l’ambito di visibilità lo spazio di memoria
associato deve essere deallocato. Nel caso di JAVA si occupa di questo il “garbage collector”.
Un oggetto può essere deallocato quando nessun riferimento punta più a quell’oggetto (obj=null;).
Non è determinabile a priori il momento in cui interverrà il gc a volte anche in casi in cui si “richiede” il suo
intervento (System.gc();).
Se serve effettuare delle operazioni prima che un oggetto venga distrutto (liberare risorse, non di memoria
perché quello già lo fa il gc, ma ad es. chiudere connessioni ecc…) è possibile definire un metodo “protected
void finalize(){…};”esso viene richiamato appena prima l’operazione di deallocazione effettuata dal gc;
ATTENZIONE: non è garantita la sua chiamata.
-It is not public because it shouldn't be invoked by anyone other than the JVM. However, it must be protected so that it can be overridden by subclasses who need to
define behavior for it.
-In general it's best not to rely on finalize() to do any cleaning up etc.
According to the Javadoc (which it would be worth reading), it is:
Called by the garbage collector on an object when garbage collection determines that there are no more references to the object.
As Joachim pointed out, this may never happen in the life of a program if the object is always accessible.
Also, the garbage collector is not guaranteed to run at any specific time. In general, what I'm trying to say is finalize() is probably not the best method to use in general
unless there's something specific you need it for. In general it's best not to rely on finalizer() to do any cleaning up etc.
According to the Javadoc (which it would be worth reading), it is:
Called by the garbage collector on an object when garbage collection determines that there are no more references to the object.
As Joachim pointed out, this may never happen in the life of a program if the object is always accessible.
Also, the garbage collector is not guaranteed to run at any specific time. In general, what I'm trying to say is finalize() is probably not the best method to use in general
unless there's something specific you need it for.
STATIC: Membri dichiarati static, sono associati alla classe e non ad una particolare istanza. Pertanto esiste
una sola copia di un campo statico, condiviso da tutte le istanze della classe; non occorre istanziare un
oggetto per usare un membro statico. Metodi statici possono accedere solo a membri statici della classe.
Sono qualificati con il nome della classe e non dell’istanza (si può anche farlo col nome dell’istanza ma non
è consigliato).
- Esempio significativo:
public class Oggetto{
static int n_obj=0;
public Oggetto() { n_obj++; }
public void finalize() { n_obj-- } //Un buon utilizzo di finalize!
} La variabile n_obj conta il numero di istanze allocate per la classe oggetto.
THIS: https://docs.oracle.com/javase/tutorial/java/javaOO/thiskey.html
(nota personale: java accepts same name for fields and constructor parameters).
PACKAGES: Si usano per evitare confusioni tra classi con lo stesso nome, organizzare meglio il codice e
consentire lo sviluppo ed il riutilizzo di librerie.
FINAL: Ha un significato differente a seconda del contesto in cui si utilizza, essa si può riferire a:
1) Tipi semplici. Può indicare che la variabile dichiarata è una costante a tempo di compilazione e può
essere pertanto sostituita nel bytecode per ottimizzare l’esecuzione. Oppure indica che quella
variabile una volta inizializzata a run-time non può più cambiare. Una variabile sia static che final
corrisponde ad una locazione di memoria comune a tutti gli oggetti che non può essere cambiata.
2) Riferimenti. Un riferimento ad un oggetto dichiarato final può essere inizializzato una sola volta e
non può essere modificato.
3) Metodi. Un metodo final non può essere cambiato nelle classi derivate. Esso può diventare una
funzione inline cioè: il compilatore copia il corpo della funzione invece che inserire un’istruzione di
salto (può migliorare l’efficienza). (vd. esempi slide).
Ricorda, un metodo private è anche final (è inutile scriverli entrambi): non potendo essere usato non
può essere ereditato; private è più forte di final; inoltre essendo il metodo oscurato la classe figlia
può creare un metodo con stesso nome, tipo e numero di argomenti di quello della classe madre.
4) Classi. Una classe final non può essere ereditata. È inutile definire final i metodi di una classe final.
NOTE: BLANK FINAL sono campi che non vengono inizializzati (variabili, riferimenti), devono essere
inizializzati nel costruttore altrimenti il compilatore segnala un errore (attenzione con il modificatore
static in quel caso bisogna inizializzare nella dichiarazione).
PARAMETRI FINAL sono parametri che non possono essere cambiati nel metodo.
EREDITARIETÀ
- COMPOSIZIONE
1) Si usa la composizione quando una classe deve fornire le funzionalità realizzate in altre classi già
esistenti. Gli attributi della nostra classe sono oggetti di classi già esistenti.
2) Occorre fare attenzione ad inizializzare gli oggetti componenti di una classe.
3) Esempio:
- EREDITARIETÀ
1) Si usa l’ereditarietà quando la nuova classe deve presentare un’estensione dell’interfaccia della
vecchia classe. Oltre al riuso di software (meno tempo di sviluppo) l’ereditarietà permette di
descrivere un sistema secondo un modello gerarchico.
2) La sottoclasse eredita tutti i metodi (operazioni) della genitrice, e può essere estesa con metodi ed
attributi locali che ne completano la descrizione (specializzazione e generalizzazione). Tale
meccanismo consente di derivare una sottoclasse da una classe data, per AGGIUNTA,
OCCULTAMENTO o per RIDEFINIZIONE di uno o più membri rispetto alla classe di partenza (che
diventa una superclasse della nuova classe).
3) La classe ereditata è detta classe base, la classe che eredita è detta classe derivata, la classe che
eredita può:
a) Utilizzare i metodi della classe ereditata
b) Definire i metodi della classe ereditata
c) Definire nuovi metodi propri
4) SINTASSI JAVA
Extends indica quale classe si vuole ereditare: java permette di ereditare una sola classe
Super: punta alla classe base
Protected: specificatore, indica che l’accesso a quell’attributo è consentito a tutte le classi del
package ed a quelle figlie
5) MECCANISMI DELL’EREDITARIETÀ
Overriding (dare precedenza): si ridefinisce il metodo della classe base specializzandone o
sostituendonde il comportamento.
Overloading: in Java l’overload di un metodo della classe base, effettuato nella classe derivata, non
causa oscuramento.
Shadowing: oscurare un metodo o un attributo della classe madre dichiarandolo privato.
6) EREDITARIETÀ E COSTRUTTORI
L’ereditarietà non fornisce alla classe derivata solo un’interfaccia uguale a quello della classe base.
Quando si crea una classe derivata essa contiene tutte le componenti della classe base.
Quindi anche tutte queste componenti devono essere inizializzate correttamente.
L’unico modo per garantire ciò correttamente è chiamare il costruttore della classe base (il quale è
in grado di effettuare le inizializzazioni correttamente).
Java inserisce automaticamente la chiamata al costruttore della classe base in quello della classe
derivata.
7) COSTRUTTORI CON ARGOMENTI
Una classe base può presentare diversi costruttori che si distinguono per numero, tipo o ordine dei
parametri.
In tal caso è il programmatore che deve scegliere quale costrutto della classe base chiamare.
Si utilizza la parola chiave super per richiamare il costruttore desiderato.
8) UPCASTING
Un oggetto della classe derivata è anche un oggetto della classe base. Tale definizione è supportata
dal linguaggio nella pratica. Un messaggio inviabile alla classe base può essere inviato anche alla
classe derivata (vd es. slide); ad esempio la classe Vector del package java.util può contenere un
oggetto di qualunque classe (perché tutte le classi Java ereditano implicitamente la classe Object).
POLIMORFISMO
1) Per polimorfismo si intende la proprietà di un’entità di assumere forme diverse nel tempo.
Un’entità è polimorfa se può fare riferimento, nel tempo, a classi diverse.
Permette di estendere un progetto già sviluppato aggiungendo nuove funzionalità e minimizzando
la quantità di codice che occorre modificare. È conosciuto anche come binding dinamico o late
binding.
2) L’azione di collegare la chiamata di un metodo al codice corrispondente è detta BINDING. Il binding
può avvenire a tempo di compilazione (early binding) o a tempo di esecuzione (late binding).
Un meccanismo con cui viene realizzato il polimorfismo è quello del binding dinamico. Il binding
dinamico consiste nel determinare a tempo d’esecuzione, anziché a tempo di compilazione, il corpo
del metodo da invocare su un dato oggetto.
3) Quando Java usa l’early binding? Quando il metodo o l’attributo è dichiarato final.
In realtà Java sa di poter utilizzare l’early binding. Un vantaggio dovrebbe essere la velocità, ma non
è apprezzabile. Usare final solo in base a criteri di progetto.
CLASSI ASTRATTE
2) Una classe si dice astratta quando uno o tutti i suoi metodi non sono implementati. Essa definisce
solo l’interfaccia delle classi derivate (ed eventualmente una parziale implementazione).
Essendo una classe astratta non definita completamente non è possibile istanziare un oggetto di tal
tipo.
3) Chiariamo con un esempio:
DOWNCASTING
Aspetto negativo dell’Upcasting: se un oggetto della classe figlia viene visto come un oggetto della classe
madre tramite Upcasting, non posso utilizzare i metodi della classe figlia non presenti nella classe madre.
Le caratteristiche della classe derivata perse durante l’Upcasting possono essere recuperate. L’operazione
di downcasting deve essere forzata poiché non è sempre lecita. È il programmatore a dover sapere cosa sta
facendo. Può generare un’eccezione a run-time (vd esempio sulle slide).
INTERFACCE
1) Il C++ supporta l’ereditarietà multipla: ereditare più classi. L’ereditarietà multipla può causare
problemi di collisione in quanto occorre supportare l’upcasting verso diverse classi.
Le interfacce permettono di gestire in modo più sofisticato gli oggetti di un progetto.
2) Le interfacce definiscono classi completamente astratte. Ogni metodo dichiarato è di default
pubblico e non può avere implementazione. Gli attributi sono di default statici e final, e non
possono essere blank (devo inizializzarli o nella dichiarazione o a run time)(PS: un’interfaccia può
contenere solo costanti).
Una classe può implementare più interfacce attraverso la parola chiave implements.
3) Solo un interfaccia può ereditare interfacce. Solo una classe può implementare interfacce.