Sei sulla pagina 1di 9

CICLO DI VITA DEL SOFTWARE: Definisce un modello per il software, dalla sua concezione iniziale fino al suo

sviluppo completo, al suo rilascio, alla sua successiva evoluzione, fino al suo ritiro.

Definizione (cosa)

Sviluppo (come)

Manutenzione (modifiche)

FASE DI SVILUPPO

Concetti chiave:

1) Astrazione (sul controllo o sui dati)


2) Modularità (organizzazione in parti, ogni parte ha interfaccia e corpo)
3) Incapsulamento e information hiding
4) Metodologie di progetto: top down (decomposizione funzionale) bottom up (composizione e
interazione tra oggetti)
5) Tipi di programmazione: procedurale, a oggetti, generica (definisce una funzione o una classe
senza specificare il tipo di una o più delle sue entità (parametri, membri); curiosità: il C++ supporta
tutti e tre i tipi di programmazione)

PROGRAMMAZIONE ORIENTATA AGLI OGGETTI

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

LINGUAGGIO JAVA: CARATTERISTICHE PRINCIPALI

1) Semplice e orientato agli oggetti (elimina costrutti pericolosi)


2) Interpretato
3) Architetturalmente neutro e portabile
4) Robusto e sicuro (controlli compile e run time)
5) Distribuito (pensato per essere eseguito in rete)
6) Dinamico (eseguibile anche in assenza di alcuni moduli caricati quando necessario)
7) Concorrente (multithreading)

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)

Tipi e variabili: java è un linguaggio fortemente tipizzato

1) Dati semplici: intero (byte,short,int,long), floating point (float,double), char, boolean


2) Variabili:
- Per essere utilizzate devono essere inizializzate
- Sono valide soltanto dal punto in cui vengono dichiarate fino alla fine del blocco di istruzioni
che le racchiude
- Non è possibile dichiarare una variabile con lo stesso nome di un’altra contenuta in un blocco
più esterno
3) Costanti: si realizzano con la keyword “final”
4) Conversioni e casting:
- Impliciti ( sono automatici, a un tipo più capiente viene assegnato un tipo meno capiente)
- Espliciti ( casting: (nuovo_tipo) variabile; )

Istruzioni di controllo flusso:

1) Condizionali:
- if, if else
- switch
2) Cicli:
- for
- while, do-while

Operatori:

1) Operatori aritmetici: + , - , * , / , % (modulo) , ++n ed n++ (incremento) , --n ed n-- (decremento)


Forme abbreviate: a+=b , a-=b , a*=b , a/=b
2) Operatori di assegnamento: =
3) Operatori di confronto: == , != , > , < , <= , >=
4) Operatori logici: ! , && (congiunzione) , || (disgiunzione inclusiva) , ^ (disgiunzione esclusiva)

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

Oggetti: gli oggetti vanno

- DICHIARATI: la dichiarazione di un oggetto equivale a dichiarare un reference


- ISTANZIATI (new): la creazione dell’oggetto rende valida la reference e alloca memoria per
l’oggetto; ATTENZIONE: tutti gli oggetti devono essere creati
- INIZIALIZZATI

Array:

- In Java un array è un oggetto (diversamente da C++)


- Si possono dichiarare array di qualsiasi tipo ( es. int[] a; int a[]; int[] a,b,c; int a[],b[]; int[] a, b[]
$equivale a$ int[] a; int[][] b; )
- Sono creati mediante la keyword new, occorre indicare un tipo e un numero intero, non
negativo, di elementi da allocare ( es. dichiarazione+creazione int v[]; v=new int[10]; oppure
int[] v = {1,2,3,4,5} )
- Accedo in questo modo es: int[] v={1,2};  v[1]=4;
- Si possono creare array di array
- Java controlla in modo rigoroso che il programmatore non tenti accidentalmente di
memorizzare o fare riferimento ad elementi dell’array tramite un indice non valido

ALCUNI METODI INCONTRATI:

Delle stringhe: stringa.substring(index1), stringa.substring(index1, index2), stringa.lenght()

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, COSTRUTTORI E DISTRUTTORI

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.

KEYWORD STATIC, THIS, PACKAGES, INFORMATION HIDING

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.

- Più classi possono essere riunite in un package dotato di nome.


- Il nome di una classe (o di un’interfaccia) va sempre qualificato con il nome del package a cui
appartiene (es. java.util.Date;). Può essere omesso: quando viene usato all’interno dello stesso
package o utilizzando lo statement “import”.
- Definizione e Creazione:
DEFINIZIONE: Il nome di un package può essere composto da più identificatori separati da “.”
CREAZIONE: Si inserisce la keyword package nella prima riga del file (deve apparire una sola
volta).

INFORMATION HIDING: Meccanismo della programmazione ad oggetti che consente di nascondere


l’implementazione della classe. Ciò si fa regolando gli accessi agli attributi di una classe da parte di oggetti
di altri classi. Si utilizzano specificatori/modificatori di accesso appositi.
Nota: perché dichiarare un metodo private? Metodi di utilità per il programmatore possono essere resi
private, in modo che coloro che utilizzano la classe da codice esterno non possano accedervi. Ciò consente
al programmatore di cambiarli o rimuoverli quando vuole. Rendere un metodo private permette a chi ha
realizzato la classe di riservarsi questa opzione.
Potremmo volere controllare il modo in cui un oggetto viene creato; potremmo proibire l’accesso ad un
costruttore ad esempio.

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À

Riuso del codice attraverso:

- 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, CLASSI ASTRATTE

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

1) Le cose viste fino ad ora possono causare dei problemi:


- Il programmatore potrebbe sbagliare il prototipo di un metodo e crearne uno nuovo invece di
ridefinirlo.
- Il programmatore potrebbe dimenticare di effettuare l’overriding.
- Il metodo della classe base richiamata potrebbe essere solo fittizio, quindi dovremmo stampare
un messaggio di errore visualizzato quando è troppo tardi.
- La classe base fittizia potrebbe essere creata e inizializzata in maniera scorretta.

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:

EREDITARIETÀ: COSTRUTTORI E DISTRUTTORI, DOWNCASTING, INTERFACCE

EREDITARIETÀ: COSTRUTTORI E DISTRUTTORI


I costruttori sono metodi speciali. Costruzioni di classi derivate:

1) Viene chiamato ricorsivamente il costruttore della classe base


2) Si comincia la costruzione dalla radice della gerarchia
3) Si istanziano gli oggetti creati nella parte dichiarativa
4) Si eseguono i costruttori

La costruzione avviene al contrario:

1) Occorre distruggere prima gli elementi della classe derivata

Perché ho ripetuto questo? ATTENZIONE: La chiamata di un metodo polimorfo all’interno di un costruttore


può essere pericoloso perché la costruzione dell’oggetto non è terminata. Soluzione: semplicemente
evitare, chiamare solo i metodi final e privati (vd esempio sulle slide).

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.