PRINCIPI DI PROGRAMMAZIONE
ORIENTATA AGLI OGGETTI
Università degli Studi di Torino
2026 Principi di Programmazione Orientata agli Oggetti
INDICE
01 - INTRODUZIONE 2
.....................................................................................................................................................................
02 - CLASSI, ATTRIBUTI E METODI 4
.......................................................................................................................................
03 - METODI DI GET E SET, IL MODIFICATORE FINAL 6
.................................................................................................
04 - COSTRUTTORI, ASSEGNAZIONI DI OGGETTI, METODO EQUALS() 8
...............................................................
05 - LA CLASSE STACK 10
............................................................................................................................................................
06 - INFORMATION HIDING 12
...................................................................................................................................................
07 - CLASSI DI ARRAY DI OGGETTI: ADDRESSBOOK E CONTACT 15
......................................................................
08 - DIAGRAMMI UML E ARRAY ESTENDIBILI 17
..............................................................................................................
09 - SECURITY LEAK 19
..................................................................................................................................................................
11 - CLASSI GENERICHE: COPPIE, NODI E PILE 21
...........................................................................................................
12 - EREDITARIETÀ E ASSERT 23
..............................................................................................................................................
13 - ESTENSIONI RIPETUTE DI CLASSI 25
............................................................................................................................
14 - TIPO ESATTO E BINDING DINAMICO 27
.......................................................................................................................
15 - ARRAY COME LISTE 29
.........................................................................................................................................................
16 - CLASSI ASTRATTE DI FIGURE 31
.....................................................................................................................................
17 - GLI ALBERI DI RICERCA 33
..................................................................................................................................................
18 - VISITA DI UN ALBERO BINARIO 35
..................................................................................................................................
19 - INTERFACCE 37
........................................................................................................................................................................
20 - INTERFACCE COMPARABLE, ITERATOR E ITERABLE 39
......................................................................................
21 - ECCEZIONI CONTROLLATE E NON CONTROLLATE 41
..........................................................................................
22 - CENNI ALLA PROGETTAZIONE ORIENTATA AGLI OGGETTI 43
........................................................................
1 Principi di Programmazione Orientata agli Oggetti
01 - INTRODUZIONE
In questo capitolo si introducono gli elementi che definiscono la prospettiva orientata agli
oggetti: oggetti, classi, responsabilità e collaborazione. Si chiarisce inoltre perché
astrazione e incapsulamento sono essenziali per progettare componenti utilizzabili senza
esporne i dettagli interni.
OSSERVAZIONE
Java è class-based
In Java gli oggetti ordinari vengono creati come istanze di classi. La classe
descrive i campi e i metodi disponibili, mentre ogni istanza conserva il proprio
stato.
Dalla classe all’oggetto
La classe è il progetto; l’oggetto è una singola realizzazione del progetto. Due oggetti della
stessa classe hanno gli stessi tipi di campi e gli stessi metodi, ma possono conservare
valori diversi. Il metodo `saluta` descrive un comportamento disponibile a ogni istanza.
class Studente {
String nome;
void saluta() {
System.out.println("Ciao, sono " + nome);
}
}
Studente ada = new Studente();
ada.nome = "Ada";
ada.saluta();
L’interfaccia come promessa
Chi usa una classe dovrebbe sapere quali operazioni può richiedere, non come esse siano
realizzate. Se la classe cambia il modo in cui memorizza i dati ma conserva i metodi
pubblici, il codice client può continuare a funzionare.
Oggetti e classi come prospettive complementari
La progettazione a oggetti descrive un sistema da due angolazioni. La prospettiva part-of
considera gli oggetti collaboranti e i servizi che si scambiano per realizzare un compito;
quella is-a organizza invece le classi in famiglie, mettendo in evidenza caratteristiche
2 Principi di Programmazione Orientata agli Oggetti
condivise e specializzazioni. Un programma OOP è quindi una rete di oggetti, ciascuno
istanza di una classe, e di classi eventualmente collegate da ereditarietà.
DEFINIZIONE
Astrazione e incapsulamento
L'astrazione definisce ciò che un oggetto rende osservabile al client, ignorando
dettagli non essenziali. L'incapsulamento protegge invece la rappresentazione e
l'implementazione che producono quel comportamento: l'interfaccia espone i
servizi promessi, mentre i dettagli interni restano nascosti.
Ogni oggetto ha identità, stato e comportamento. Lo stato è dato dai valori correnti delle
proprietà; il comportamento è l'insieme dei servizi accessibili tramite metodi. La classe
descrive struttura e comportamento comuni alle proprie istanze, mentre le responsabilità di
un oggetto sono i servizi che offre nei diversi ruoli assunti nel sistema.
Per esempio, in un programma di gestione universitaria, uno studente può collaborare con
un corso e con un servizio d'iscrizione. Lo studente non deve conoscere come il servizio
registra i dati: gli invia una richiesta attraverso operazioni pubbliche. Questa collaborazione
è la prospettiva part-of; distinguere studenti, corsi e servizi in classi con ruoli diversi
riguarda invece l'astrazione e la prospettiva is-a.
La scelta di un'astrazione dipende da chi usa l'oggetto. Un conto bancario espone
operazioni come depositare e prelevare, ma non dovrebbe esporre il modo in cui
memorizza il saldo. Nascondere la rappresentazione permette di cambiarla senza
costringere ogni client a cambiare a sua volta.
3 Principi di Programmazione Orientata agli Oggetti
02 - CLASSI, ATTRIBUTI E METODI
Qui si passa dai concetti generali alla loro rappresentazione in Java: dichiarazione di classi,
creazione di istanze, riferimenti in memoria, visibilità e differenza tra membri di istanza e
membri statici. Il capitolo mostra anche come Java compila ed esegue i programmi.
OSSERVAZIONE
Attenzione a null
`null` non è un oggetto speciale con campi vuoti: è un riferimento che non indica
alcuna istanza. Per questo `x.metodo()` fallisce se `x` vale `null`, anche se il
metodo non usa campi.
Riferimento e istanza
La variabile `a` contiene un riferimento all’oggetto creato. Assegnandola a `b` si copia quel
riferimento: i due nomi indicano la stessa istanza. Il confronto `a == b` risulta quindi vero.
Studente a = new Studente();
a.nome = "Ada";
Studente b = a;
b.nome = "Lin";
System.out.println(a.nome); // Lin
System.out.println(a == b); // true
Membro statico e membro di istanza
Il campo `numero` è indipendente per ogni contatore; `creati` è unico e condiviso dalla
classe. Per questo si incrementa nel costruttore e si legge con `Contatore.creati`.
class Contatore {
static int creati = 0;
int numero;
Contatore(int numero) {
this.numero = numero;
creati++;
}
}
Una classe definisce i campi e i metodi ammessi per le sue istanze. Creare un oggetto con
new alloca l'istanza nell'heap e restituisce un riferimento: la variabile contiene il riferimento,
4 Principi di Programmazione Orientata agli Oggetti
non l'oggetto stesso. La JVM usa inoltre lo stack per i frame delle chiamate e le variabili
locali, e un'area associata alle classi per le informazioni di classe e i membri statici.
Visibilità e membri di classe
Una classe senza modificatore è accessibile nel proprio package; una classe public è
accessibile anche da altri package. Un file Java può dichiarare al massimo una classe
pubblica e il nome del file deve corrispondere a quello della classe. Una classe è avviabile
direttamente se contiene main; altrimenti può comunque essere usata come componente
da altre classi.
Un membro di istanza appartiene a ciascun oggetto; un membro static è condiviso dalla
classe. I metodi di istanza ricevono implicitamente this, riferimento all'oggetto destinatario.
toString() fornisce una rappresentazione testuale e viene invocato implicitamente, per
esempio, da println quando riceve un oggetto.
Java passa sempre gli argomenti per valore: nel caso di un oggetto viene copiata la
variabile-riferimento, perciò il metodo può operare sul medesimo oggetto senza poter
riassegnare la variabile del chiamante.
A differenza di una struct C, una classe Java può associare operazioni ai dati e
nasconderne la rappresentazione. Il sorgente Java viene compilato in bytecode, eseguito
dalla JVM: la macchina virtuale rende il bytecode portabile tra piattaforme compatibili, pur
introducendo il costo del proprio livello di esecuzione.
Una variabile locale che contiene un riferimento non è l'oggetto: se l'oggetto diventa
irraggiungibile da ogni riferimento, il garbage collector può recuperare la memoria. Il valore
`null` indica invece che una variabile non riferisce alcun oggetto; chiamare un metodo
attraverso `null` provoca una `NullPointerException`.
I campi di istanza ricevono valori iniziali predefiniti, mentre le variabili locali devono essere
inizializzate prima dell'uso. I metodi statici non hanno un oggetto destinatario e non
possono usare `this`; per questo si usano per operazioni o dati comuni alla classe, non per
comportamenti che dipendono dallo stato di una specifica istanza.
5 Principi di Programmazione Orientata agli Oggetti
03 - METODI DI GET E SET, IL MODIFICATORE FINAL
Il capitolo approfondisce come proteggere lo stato degli oggetti attraverso campi privati e
metodi di accesso controllato. Getter, setter e `final` vengono considerati come strumenti
di progettazione per mantenere dati validi, non come convenzioni da applicare
automaticamente a ogni campo.
OSSERVAZIONE
final non significa immutabile
Un riferimento dichiarato `final` non può essere riassegnato, ma l’oggetto raggiunto
tramite quel riferimento può ancora essere modificabile. È una distinzione
frequente nelle domande d’esame.
Getter, setter e validazione
Il setter è un punto di controllo: se il dato non rispetta le regole dell’oggetto, non viene
accettato. Omettere `setEta` renderebbe l’età leggibile ma non modificabile dal client dopo
la costruzione.
class Persona {
private int eta;
public int getEta() { return eta; }
public void setEta(int eta) {
assert eta >= 0;
this.eta = eta;
}
}
Un riferimento final non rende immutabile l’oggetto
Dopo l’assegnazione non è possibile far puntare `data` a un’altra lista. È però possibile
aggiungere elementi alla lista: è immutabile il riferimento, non necessariamente il suo
contenuto.
final java.util.List<String> nomi = new java.util.ArrayList<>();
nomi.add("Ada"); // consentito
// nomi = new java.util.ArrayList<>(); // errore
In progettazione, un attributo descrive una proprietà concettuale; nel codice la proprietà è
rappresentata da un campo. Lo stato è l'insieme dei valori assunti dai campi in un dato
6 Principi di Programmazione Orientata agli Oggetti
momento.
Accesso controllato e uguaglianza
Dichiarare privati i campi impedisce al client di modificarli direttamente. I getter offrono
lettura controllata e i setter, quando opportuni, possono verificare i valori prima di
aggiornare lo stato. Omettere un setter permette di esporre una proprietà in sola lettura.
Due riferimenti sono identici se indicano lo stesso oggetto; oggetti distinti possono invece
essere uguali secondo i valori o il criterio logico scelto dalla classe.
Costanti e caso Calculator
Un campo final deve essere assegnato una sola volta, normalmente nel costruttore. Se è
primitivo, il valore non cambia; se contiene un riferimento, non si può riassegnare il
riferimento, ma l'oggetto puntato può restare mutabile. static final rappresenta una
costante condivisa dalla classe. Nel caso Calculator, l'interfaccia pubblica può limitarsi a
execute, lasciando privati pila e operazioni ausiliarie; la notazione RPN colloca gli operatori
dopo gli operandi e una pila consente di valutare le espressioni in ordine LIFO.
L'incapsulamento non richiede automaticamente un getter e un setter per ogni campo. Un
metodo pubblico dovrebbe rappresentare un'operazione significativa per il dominio e
mantenere valide le regole dell'oggetto. Per una data di nascita, per esempio, può essere
più corretto accettare la data completa e convalidarla che offrire setter indipendenti per
giorno, mese e anno.
Una copia di riferimento e una copia profonda sono cose diverse. Se un campo `final` punta
a una lista, il riferimento non può cambiare, ma la lista sì. Per rendere immutabile anche il
contenuto occorre non esporre la lista modificabile, oppure restituire una copia non
modificabile o una copia difensiva. 7 Principi di Programmazione Orientata agli Oggetti
04 - COSTRUTTORI, ASSEGNAZIONI DI OGGETTI,
METODO EQUALS()
Si esamina la fase di costruzione degli oggetti e il modo in cui variabili e riferimenti si
comportano dopo un assegnamento. Il capitolo distingue inoltre il confronto tra identità e
uguaglianza logica, spiegando il ruolo dei costruttori sovraccaricati e di `equals`.
OSSERVAZIONE
String è immutabile
Le stringhe Java non vengono modificate sul posto: operazioni come
concatenazione producono una nuova stringa. Perciò `equals` confronta il
contenuto, mentre `==` continua a confrontare i riferimenti.
Costruttori sovraccaricati
Il primo costruttore crea una persona senza un’età nota; il secondo permette di
inizializzarla subito. Il compilatore sceglie la firma che corrisponde agli argomenti passati a
`new`.
class Persona {
private String nome;
private int eta;
Persona(String nome) { this(nome, 0); }
Persona(String nome, int eta) {
this.nome = nome;
this.eta = eta;
}
}
Identità e uguaglianza logica
Senza override, `equals` ereditato da `Object` equivale a confrontare l’identità. Per
confrontare il contenuto, una classe ridefinisce `equals(Object)`; `==` resta invece un
confronto fra riferimenti.
String x = new String("Java");
String y = new String("Java");
System.out.println(x == y); // false
System.out.println(x.equals(y)); // true 8 Principi di Programmazione Orientata agli Oggetti
L'espressione new C(...) alloca l'oggetto e invoca il costruttore per inizializzarne lo stato. Se
non è dichiarato alcun costruttore, Java ne fornisce uno senza argomenti; appena si
dichiara un costruttore, quello implicito non è più disponibile, salvo dichiararlo
esplicitamente. I costruttori hanno il nome della classe e non dichiarano un tipo di ritorno.
Più costruttori possono coesistere se le loro firme differiscono per numero o tipi dei
parametri.
Riferimenti e uguaglianza
L'operatore == confronta i riferimenti: è vero quando entrambi indicano lo stesso oggetto (e
null == null è vero). Il metodo equals definito da Object ha inizialmente la stessa
semantica; una classe può sovrascriverlo per esprimere l'uguaglianza logica, confrontando
le proprietà pertinenti. L'assegnazione x = y copia il riferimento e crea un alias, non una
copia dell'oggetto. Copiare i campi in una nuova istanza produce invece due oggetti
separati, la cui uguaglianza dipende dall'implementazione di equals.
Il costruttore dovrebbe portare l'oggetto in uno stato utilizzabile fin dalla creazione. Se
esistono più inizializzazioni, un costruttore può delegare a un altro con `this(...)`, evitando di
ripetere assegnazioni e controlli. L'overloading viene risolto staticamente: contano il
numero e i tipi degli argomenti disponibili al compilatore.
Quando si ridefinisce `equals`, il criterio deve riflettere l'identità logica scelta per la classe:
per un punto possono bastare le coordinate, mentre per una persona potrebbe servire un
identificativo stabile. Il controllo dei tipi e di `null` evita cast non sicuri; le classi che
sovrascrivono `equals` dovrebbero anche mantenere coerente `hashCode`, così da
funzionare correttamente nelle collezioni basate su hash.
9 Principi di Programmazione Orientata agli Oggetti
05 - LA CLASSE STACK
Questo capitolo usa la pila per collegare una struttura dati concreta ai principi di
incapsulamento e invariante. Si studiano le operazioni LIFO su un array, il significato del
contatore e l’uso delle asserzioni per rilevare violazioni del contratto.
OSSERVAZIONE
Le asserzioni sono disattivate per default
Il codice `assert` viene controllato solo se la JVM è avviata con `-ea`. Non usarlo
per controlli di sicurezza o validazione che devono avvenire anche nella versione
distribuita.
Operazioni fondamentali su una pila con array
Con arr
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.