Copyrigtht © 2000 Universita' di Firenze. All rights reserved.
Free license available.
Revisori: Prof. Franco Pirri 
 , Ing. Claudio Bizzarri ![]()
|
Una classe consente di creare un nuovo tipo di dati
definendo la struttura astratta di un certo insieme di entità.
In pratica tramite una classe si possono definire tutte le proprietà (identificabili
tramite l'assegnazione di un valore) che sono comuni ad un certo insieme di entità e
tutte le operazioni che su queste entità si possono effettuare.
Le proprietà identificabili tramite l'assegnazione di un valore costituiscono gli
attributi (o variabili di
istanza) di una classe e, in pratica, ne definiscono la struttura.
Le operazioni che si possono compiere sulle entità di una classe vengono dette
metodi e costituiscono lo strumento attraverso il
quale è possibile manipolare gli attributi.
Se ad esempio vogliamo sviluppare la classe AUTO possiamo supporre che ogni
auto sia contraddistinta da:
![]() |
Come abbiamo già detto in precedenza una classe rappresenta un modello astratto che
definisce le caratteristiche comuni ad un certo insieme di entità.
Il processo di istanziazione è il processo attraverso
il quale vengono creati elementi (o istanze) appartenenti ad una specifica classe: le
istanze di una classe vengono normalmente chiamate oggetti
.
L'istanziazione di un nuovo oggetto avviene per mezzo di un metodo della classe: tale
metodo particolare è conosciuto come costruttore.
Rifacendoci all'esempio considerato nella precedente slide un oggetto della classe
AUTO potrebbe essere dato da:
![]() |
L'incapsulazione è alla base della programmazione ad
oggetti e consiste nel nascondere alcuni dettagli relativi all'implementazione di una
classe, impedendo l'accesso ad essi da parte di altri frammenti di codice esterni alla
classe stessa.
Di solito vengono nascosti gli attributi (o variabili di istanza) di una classe
permettendo all'utente di utilizzare soltanto i metodi messi a disposizione dalla classe
stessa per operare sui suoi attributi.
I metodi di una classe costituiscono la sua interfaccia
verso l'esterno e sono tutto ciò che un utente deve conoscere per poter utilizzare la
classe nelle proprie applicazioni.
L'incapsulazione consente di creare più versioni diverse di una stessa classe (dovute
magari a miglioramenti operati nel corso del tempo) senza la necessità di modificare
il codice delle applicazioni che utilizzano tale classe, a patto di mantenere invariata
la sua interfaccia.
![]() |
Classi base e classi derivate
Il meccanismo dell'ereditarità è una delle basi su
cui poggia la programmazione orientata agli oggetti e consente di creare
classificazioni gerarchiche e di aumentare la
riusabilità del codice.
Tramite l'ereditarietà è possibile creare una classe generale, detta
classe base o
superclasse, che definisce le caratteristiche comuni ad un certo insieme di
oggetti.
Successivamente la classe base può essere ereditata
da una o più classi, che prendono il nome di classi
derivate o sottoclassi, ognuna delle
quali aggiunge alla classe ereditata soltanto i suoi elementi specifici.
In pratica, per mezzo del meccanismo dell'ereditarietà, è possibile definire una classe
specificando soltanto le sue differenze rispetto ad un'altra classe data.
Ciò risulta possibile in quanto:
![]() |
Il concetto di polimorfismo è strettamente legato a
quello di ereditarietà e si riferisce alla capacità di ottenere comportamenti diversi
inviando gli stessi segnali ad oggetti diversi (ovvero invocando gli stessi metodi su
oggetti diversi).
Il polimorfismo può essere caratterizzato dalla frase "un'interfaccia, più metodi"
e poggia le sue basi sulla possibilità, offerta praticamente da tutti i linguaggi di
programmazione orientati agli oggetti, di ridefinire in classi derivate il comportamento
(cioè l'implementazione) di uno o più metodi ereditati da una classe base.
In pratica, dato un insieme di classi che possono anche essere in relazione gerarchica,
ogni classe può implementare in modo diverso uno stesso metodo presente anche nelle
altre classi.
Il compilatore (o l'interprete) del linguaggio, potendo sempre conoscere la classe a cui
appartiente un dato oggetto, è capace di determinare a run-time (al tempo di
esecuzione) il metodo corretto da eseguire.
Il polimorfismo permette così di mantenere inalterata l'interfaccia di una classe
derivata, almeno per quanto concerne i metodi ereditati dalla classe base, anche se i
metodi da essa implementati devono svolgere operazioni diverse rispetto a quelle
compiute dai corrispondenti metodi della classe base.