Sei sulla pagina 1di 70

Fondamenti

di programmazione
ad oggetti

Introduzione
Programmi semplici e non orientati agli oggetti possono constare di una
lunga lista di istruzioni (statements). Programmi pi complessi
raggruppano spesso piccoli blocchi di istruzioni in funzioni o subroutines, ciascuna delle quali realizza un obiettivo particolare. Per
programmi cos strutturati piuttosto comune che qualche dato sia
globale e cio accessibile e modificabile da qualsiasi sezione del
programma. Con l'aumento della dimensione dei programmi, permettere
ad ogni funzione di modificare qualsiasi dato rende inevitabile la
propagazione di numerosi errori (bugs).

Lapproccio della programmazione orientata agli oggetti, d'ora in poi


chiamata OOP, invece, fa s che il programmatore localizzi i dati dove
non siano direttamente accessibili dal resto del programma. Ai dati stessi
si pu accedere chiamando delle funzioni scritte
in modo particolare, comunemente definite metodi, le quali, o sono
impacchettate con i dati oppure ereditate da oggetti classe. Tali funzioni
agiscono come intermediari per recuperare o modificare i dati che
controllano. Lunit di programmazione nella quale i dati sono associati
ad una serie di metodi per gestirli viene definita in OOP un oggetto.

Larchitettura Software
Larchitettura software di un programma informatico linsieme di dati
strutturali necessari per ragionare su di esso: tali dati comprendono gli
elementi del software, le relazioni che intercorrono tra di essi e le
propriet degli uni e delle altre. Per definizione, larchitettura software
linsieme di regole pratiche, criteri e schemi di progettazione che
regolano:
la suddivisione del problema e del sistema informatico che si deve
costruire per risolverlo in moduli discreti;
le tecniche per creare interfacce fra tali moduli;
le tecniche per gestire la struttura generale ed il flusso del programma;

le tecniche per interfacciare il sistema allambiente (cio al linguaggio di programmazione);


luso corretto di approcci, tecniche e strumenti di sviluppo e distribuzione.
Gli scopi primari dellarchitettura sono:
- la definizione dellambiente un sistema (e cio del linguaggio informatico
relativo) e la definizione dei suoi requisiti non funzionali, di quelle qualit so
relative a ci che esso e non a ci che fa (requisiti funzionali).
Sono requisiti non funzionali quelli osservabili a runtime, come ad
esempio la sicurezza e la facilit di utilizzo e quelli incorporati nella
struttura statica del sistema come, ad esempio, la manutenibilit e
lespansibilit.

La definizione del progetto informatico viene seguita da quella della


sua realizzazione funzionale in accordo con le regole dellarchitettura.
Larchitettura importante perch:
limita la complessit del programma consentendone la suddivisione in elementi pi semplici (moduli o subroutines);
fa s che vengano applicate le procedure migliori (best practice);
conferisce consistenza e uniformit;
consente il riutilizzo di moduli (subroutines) del programma.

Obiect Oriented Programming


LOOP una filosofia di progettazione che utilizza linguaggi di
programmazione diversi da quelli impiegati dai vecchi linguaggi
procedurali (come il Pascal ed il C).
un tipo di programmazione in cui gli sviluppatori non si limitano a
definire il tipo di dati in una struttura dati (una struttura dati un modo
particolare di immagazzinare ed organizzare dati in un computer di
modo che possano essere utilizzati in modo efficiente) ma definiscono
anche i tipi di operazioni (funzioni) che possono essere applicate ad
essa.
Cos la struttura dati diventa un oggetto che comprende sia dati che
funzioni.

I programmatori, inoltre, possono mettere in relazione i vari oggetti


(un oggetto pu ereditare le caratteristiche di un altro).
Uno dei principali vantaggi delle tecniche OOP, rispetto alle
tecniche procedurali, consiste nel fatto che offrono al programmatore
la possibilit di creare moduli autosostenibili che non devono
essere modificati se si aggiunge un nuovo tipo di oggetto, rendendo
il programma pi facile da modificare (meno rigido).
Un programma orientato agli oggetti conterr di solito differenti tipi
di oggetti ed ogni tipo corrisponder o ad un serie particolare di dati
complessi da gestire, oppure ad un elemento od un concetto del
mondo reale, come per esempio un conto corrente postale, un calciatore o una macchina per il movimento.
Un programma potrebbe benissimo contenere pi copie dello stesso

oggetto, una per ogni controparte del mondo reale con cui il programma ha a che fare. Per esempio ci potrebbe essere un oggetto calciatore
per ciascun calciatore reale della serie A e ciascuno di essi sarebbe simile agli altri dal punto di vista dei metodi disponibili per manipolare
o leggere i suoi dati, i quali sarebbero per diversi per ogni specifico
atleta (nome, et, ruolo, ).
Si pu immaginare che gli oggetti siano una serie di dati impacchettati in
una serie di funzioni progettate per far s il loro utilizzo sia al contempo
semplice ed appropriato.
Un oggetto pu inoltre essere in grado di mettere a disposizione semplici metodi standardizzati per eseguire determinate operazioni sui
suoi dati e ci senza rendere accessibile al resto del programma il
modo in cui tali operazioni vengono realizzate.

Ci consente di modificare la struttura interna o i metodi di un


oggetto senza la necessit di modificare il resto del programma.
Tale caratteristica diventa particolarmente utile se il codice di un
programma scritto da pi di un programmatore oppure se
lobiettivo il riutilizzo di codice tra due programmi diversi.
LOOP una tecnologia basata non tanto sulle funzioni quanto sui dati
con programmi costituiti da moduli autosufficienti (classi), ciascuna
istanza dei quali (oggetto della classe) contiene tutte le informazioni
necessarie per manipolare la sua struttura dati (membri).
Un programma orientato agli oggetti si pu considerare una collezione
di oggetti interattivi ciascuno dei quali in grado di processare dati e
di scambiare messaggi con gli altri.
Ciascun oggetto ununit operativa autonoma, con un proprio ruolo

ed una propria responsabilit, le cui azioni (metodi) sono strettamente


associate alloggetto stesso.
Tre dei concetti basilari, nella programmazione orientata agli oggetti,
sono le classi, gli oggetti ed i metodi ma sono notevolmente importanti
anche concetti quali quelli di astrazione, incapsulamento, ereditariet e
polimorfismo.

Oggetti
Un oggetto un entit che pu eseguire, o sulla quale si pu eseguire,
uninsieme di attivit ad essa correlate: tali attivit definiscono
il suo comportamento. Gli oggetti sono le entit fondamentali che
vengono utilizzate in un sistema orientato agli oggetti al momento
dellesecuzione del programma (runtime): essi interagiscono tra di loro
scambiandosi informazioni e ci anche senza essere a conoscenza di
codice o dati relativi.
Gli oggetti sono caratterizzati da due propriet:
1. identit: le caratteristiche di un oggetto che permettono di
distinguerlo da altri;

2.

stato: descrizione dei dati (propriet) immagazzinati nelloggetto.

Ogni oggetto inoltre caratterizzato dai propri metodi, che descrivono


il comportamento dell'oggetto stesso.
Cos, ad esempio, loggetto motocicletta avr le propriet marca, modello, capacit del serbatoio, tipo di freni, modello di cambio ed i
metodi accelerare, frenare, cambiare marcia, rifornirsi di benzina....
Formalmente, in OOP, un oggetto definito come una delle istanze
di una classe la quale, prima di poter essere usata nel software, deve
essere istanziata in un oggetto. Possono esistere molteplici istanze di
una data classe.

Classi
Una classe la rappresentazione generale di una certa tipologia di oggetti.
In OOP, una classe un costrutto usato come stampo (progetto, prototipo), che definisce le variabili e i metodi comuni a tutti gli oggetti
di una certa specie, utilizzato per ottenere, al momento di esecuzione
del programma, delle realizzazioni specifiche della classe stessa (istanze
della classe, oggetti della classe o semplicemente oggetti).
Una classe definisce dei membri costitutivi che consentono a tali istanze
di avere uno stato (attributi) ed un comportamento (metodi).
Come le sue istanze, di cui una generalizzazione, una classe consta
di un nome, di una serie di attributi e di una serie di metodi.
Nel mondo reale si incontrano spesso parecchi elementi

dello stesso genere. Possono esistere, per esempio, migliaia di motociclette dello stesso tipo ciascuna delle quali, nel linguaggio OOP,
unistanza della classe motocicletta. Una classe pu essere rappresentata schematicamente come segue:
Teacher
- age: int
- name : string
+ Teacher (): void
+ DoTeach (object): boolean
<<property>>
+ Name () : string
+ Age () : int

Il codice per creare unistanza di una classe il seguente:

public class Teacher


{
}
Teacher objectTeacher = new Teacher();
Loggetto della classe Teacher, denominato objectTeacher,
stato istanziato dalla classe Teacher (instanziazione della classe).

Identificazione e progettazione di una classe


La progettazione di un software non adeguata se, nonostante il
software stesso soddisfi alle richieste per cui stato progettato, esso
presenta una o pi delle seguenti caratteristiche:
1. difficile da modificare in quanto una modifica in una sua
parte si riflette su troppe altre parti del sistema (rigidit in contrapposizione a flessibilit).
2. quando si modifica una parte si provoca inaspettatamente la
rottura di altre parti (fragilit in contrapposizione a robustezza).
3. difficile riutilizzarlo in unaltra applicazione perch non lo si
pu districare dallapplicazione corrente (immobilit in contrapposizione a riutilizzabilit).

Ci che rende un progetto rigido, fragile ed immobile linterdipendenza dei moduli al suo interno.
La rigidit dipende dal fatto che un singolo cambiamento in modulo
di un software, i cui moduli siano fortemente dipendenti tra di loro,
provoca una cascata di cambiamenti in moduli dipendenti.
Un programma fragile se un singolo e semplice cambiamento provoca linsorgere di problemi in aree che non sembrerebbero correlate
a quella in cui si realizzato il cambiamento stesso. Nellovviare a
questi problemi se ne provocano dei nuovi di modo che la manutenzione del software diventa praticamente impossibile.
Un progetto immobile quando i suoi moduli, che si vogliano eventualmente riutilizzare in un altro progetto, dipendono strettamente da
altri, che non sono richiesti, di modo che risulta pi conveniente ri-

scriverli ex novo piuttosto che separarli da quelli che non occorrono.


Nel caso della progettazione di una classe le tecniche utilizzate variano da un progettatore allaltro e lo stato dellarte ancora, appunto,
piuttosto artigianale.
Esistono comunque alcuni principi che opportuno seguire al fine di
ottenere un software flessibile, robusto e riutilizzabile.
Il principio di responsabilit singola: una classe dovrebbe avere una
sola responsabilit, cio una sola funzione da realizzare, per rendere
minimo (uguale ad 1) il numero di possibilit di modificazioni.
Il principio di apertura e chiusura: oggetti software come classi, moduli, funzioni devono essere espandibili ma non modificabili. Quando
una singola modificazione in un programma si riflette in una cascata
di modificazioni nei moduli correlati, esso diventa rigido, fragile im-

prevedibile e non riutilizzabile. Le classi quindi devono essere costruite in modo tale da non cambiare mai e le eventuali nuove richieste, cui deve andare incontro un programma, devono essere soddisfatte non modificando il codice vecchio, gi funzionante, ma aggiungendone del nuovo.
Il principio dellinversione della dipendenza: le classi di livello gerarchico superiore, che hanno caratteristiche pi astratte e generali, non
devono dipendere da quelle di livello inferiore, con carattere pi concreto e specifico, ma deve essere il contrario: ci per impedire che
una modifica a livello particolare si rifletta a livello generale.
Per identificare correttamente una classe necessario riconoscere ed
elencare fino al livello pi elementare tutte le funzioni (operazioni)
che il sistema informatico dovr essere in grado di eseguire.

Si passa quindi a raggruppare le varie funzioni in classi (con ciascuna


classe che raggrupper funzioni dello stesso tipo).
In ogni caso, una classe ben definita deve costituire un raggruppamento significativo di una serie di funzioni e deve consentire la riutilizzabilit incrementando nel contempo lespandibilit e la manutenibilit
del sistema complessivo.
Nel mondo del software sempre consigliabile lapplicazione del
concetto del divide et impera.
Lanalisi di un sistema nella sua globalit sempre una cosa piuttosto
difficile. Lapproccio migliore consiste nellidentificare prima i moduli del sistema e quindi analizzarli separatamente per riconoscere le
classi.
Un sistema informatico pu essere costituito da numerose classi, la

cui gestione pu comportare diversi problemi.


Per risolverli i progettatori usano diverse tecniche che possono essere
divise in quattro gruppi concettuali fondamentali, che sono i quattro
concetti principali della programmazione orientata agli oggetti,
denominati incapsulamento, astrazione, ereditariet e polimorfismo.

Incapsulamento (o segregazione delle informazioni).


Lincapsulamento una metodica che associa codice e dati in un oggetto e li mantiene entrambi al sicuro da interferenze esterne e/o da
utilizzazioni scorrette: si isolano dati e codici particolari da altri dati e
codici.
Esso consiste nellinclusione in un oggetto di un programma di tutte
le risorse di cui esso ha bisogno per funzionare: fondamentalmente
metodi e dati.
In OOP lincapsulamento realizzato principalmente tramite la creazione di classi le quali rendono accessibili al resto del programma (altre classi) metodi e propriet ma non i dati, che risultano accessibili
solo alle funzioni immagazzinate nella stessa classe.

La classe una specie di contenitore, o capsula o cella, che incapsula


la serie di metodi, attributi e propriet da fornire, a richiesta, alle altre
classi. In questo modo, lincapsulamento permette che una classe possa modificare la sua realizzazione interna senza interferire con il funzionamento globale del sistema.
Il concetto base dellincapsulamento di tener segregate le modalit
di funzionamento di una classe ma di permettere luso delle sue funzionalit.
Una classe pu utilizzare funzioni e/o propriet rese disponibili da
unaltra in molte maniere diverse.
Nel contesto dellOOP esistono varie tecniche che consentono a classi diverse di correlarsi: associazione, aggregazione e composizione.

Associazione, aggregazione e composizione.


In OOP la composizione di oggetti un modo per combinare oggetti
semplici in oggetti pi complessi. Un esempio di composizione, nel
mondo reale, la relazione tra unautomobile e le sue parti:
lautomobile has-a o composta da oggetti quali il volante, i sedili,
la scatola del cambio ed il motore.
Se, come nei linguaggi dellOOP, gli oggetti sono tipizzati, allora
possono essere compositi o meno e la composizione pu essere
considerata una relazione tra tipi: un oggetto di tipo composito
(automobile) has a un oggetto di tipo pi semplice (ruota).
La composizione non va confusa con la sottotipizzazione, che un
procedimento consistente nellaggiungere dettagli ad un oggetto per
ottenere oggetti pi specifici. Per esempio le automobili sono un tipo

particolare di veicoli: car is a vehicle.


La sottotipizzazione non descrive una relazione tra oggetti diversi ma
afferma che oggetti di un certo tipo sono anche oggetti di un tipo pi
generale.
Nella notazione UML (Unifyed Modelling Language) la composizione
rappresentata da un rombo pieno e da una linea continua.
Laggregazione, una forma pi generale della composizione, rappresentata da un rombo vuoto e da una linea continua.
composizione:

Car

aggregazione:

Pond

Carburetor

Duck

// Composition
class Car
{
private:
Carburetor* carb;
public:
Car() : carb(new Carburetor()) { }
virtual ~Car() { delete carb; }
};

// Aggregation
class Pond
{
private:
std::vector<Duck*> ducks;
};
Laggregazione differisce dalla composizione in quanto non implica
il possesso. Nella composizione se loggetto possessore viene distrutto quelli posseduti subiscono la stessa sorte.
Per esempio una universit possiede diversi dipartimenti (chimi-ca,
fisica, ) e ogni dipartimento ha un certo numero di professori. Se
luniversit chiude, i dipartimenti smettono di esistere ma i professori continuano la loro esistenza. Quindi ununiversit pu essere

considerata una composizione di dipartimenti mentre i dipartimenti


hanno aggregazioni di professori (unaltra differenza che un professore potrebbe lavorare in pi di un dipartimento ma un dipartimento
non pu far parte di pi di ununiversit).
University

Department

Professor

In OOP un associazione definisce una relazione tra classi di oggetti


che permette ad un oggetto istanza di far s che un altro compia unazione in sua vece.
Questo tipo di relazione strutturale in quanto specifica che oggetti
di un dato tipo sono connessi ad oggetti di un altro e non collegata
al comportamento.

Classe A

Classe B

Classe A

Classe B

A meno che non sia diversamente specificato, lassociazione bidirezionale, anche se pu essere limitata ad una sola direzione (in UML
ci viene rappresentato con una linea continua e, rispettivamente, con
una freccia che punta in direzione della classe che viene utilizzata.
Per i principianti il concetto di associazione pu generare confusione,
dovuta non solo a questo concetto, ma anche ai due concetti di
aggregazione e composizione.

Un modo per comprendere analogie e differenze tra questi tre utili


concetti quello di esaminarli assieme.
Lassociazione una (*a*) relazione tra due classi in cui una delle
due utilizza laltra. Laggregazione invece un tipo particolare di
associazione, la (*the*) relazione tra due classi. Se un oggetto di
una classe possiede (*has*) un oggetto di unaltra, se il secondo
una parte del primo (relazione di inclusione) allora si dice che c
unaggregazione tra le due classi. A differenza dellassociazione,
laggregazione specifica sempre la direzione.
public class Academy
{
private Secretary academySecretary = new Secretary();
}

Academy
- academySecretary : Secretary

Secretary
- name : string

<<property>>
+ academySecretary () : Secretary

In questo caso si pu dire che Academy aggrega Secretary o che ha


un (*has-a*) Secretary.
Una Academy, per, pu esistere anche senza un Secretary.
I Courses, invece, non possono esistere senza lAcademy.
La durata di vita di uno o pi Courses dipendente dalla durata di
vita dellAcademy. Qualora lAcademy venga chiusa i Courses ces-

sano di esistere e in questo il caso si dice che lAcademy composta di


Courses: questa composizione pu essere considerata come un tipo
particolare di aggregazione.
Un fattore molto importante, che spesso viene dimenticato, quello
relativo alla durata di vita.
Due classi legate da una relazione di composizione sono interdipendenti
per quanto riguarda la durata di vita.
Academy

Course
- name : string

- academySecretary : Secretary

<<property>>
+ academySecretary () : Secretary

Secretary
- name : string

Nel caso che non esista interdipendenza tra la durata di vita di diverse
classi, la relazione sar di tipo aggregazione piuttosto che di tipo
composizione.
Se se si desidera, pertanto, che due classi siano legate da una
relazione di composizione, il modo migliore per ottenere ci consiste
nel definire luna allinterno dellaltra: in questo modo la classe
esterna pu realizzare le sue funzionalit ed il ciclo di vita della classe
interna legato a quello della classe esterna.
In sintesi, si pu affermare che l'aggregazione un tipo particolare di
associazione e che la composizione un tipo particolare di aggregazione.

Association Aggregation Composition

Astrazione e generalizzazione
Lastrazione consiste nel mettere laccento sulle caratteristiche essenziali tralasciando i dettagli specifici e le precisazioni.
Limportanza dellastrazione, essenziale nello sviluppo software,
consiste nel fatto che essa consente di omettere i dettagli irrilevanti e
di utilizzare nomi per gli oggetti di riferimento.
Essa mette laccento su ci che un oggetto o fa, piuttosto di come
rappresentato o di come funziona e questo approccio fondamentale
per controllare la complessit di grandi programmi.
Mentre lastrazione diminuisce la complessit eliminando i dettagli
irrilevanti, la generalizzazione ottiene lo stesso risultato rimpiazzando una serie di entit che realizzano funzioni simili con un unico co-

strutto informatico.
La generalizzazione amplia unapplicazione in modo che possa comprendere un insieme pi esteso di oggetti dello stesso tipo o di tipo
diverso.
I linguaggi di programmazione realizzano la generalizzazione
tramite variabili, parametrizzazione, tipi generici e polimorfismo.
Si accentuano le somiglianze tra gli oggetti e ci aiuta a tenere sotto
controllo la complessit, raccogliendo entit individuali in gruppi e
fornendo unentit rappresentativa che si pu usare per specificare
ogni componente individuale di un gruppo.
Lastrazione e la generalizzazione sono spesso usate di concerto.
Le entit astratte vengono generalizate tramite parametrizzazione per
aumentarne lutilit.

Con la parametrizzazione, una o pi parti di unentit sono


rimpiazzate da un nome nuovo e che usato come un parametro.
Si invoca lentit astratta parametrizzata legando il parametro ad un
argomento.

Classi astratte
Le classi astratte, dichiarate con la parola chiave abstract, non possono essere istanziate.
Possono essere utilizzate solamente come superclassi per altre classi
che estendono la classe astratta.
La classe astratta un concetto la cui realizzazione si completa nel
momento in cui esso viene realizzato da una sottoclasse.
Inoltre una classe pu ereditare solo da una classe astratta (pu per
realizzare diverse interfacce), deve sovrascrivere tutti i suoi metodi
e le sue propriet astratti e pu sovrascrivere i suoi metodi e le sue
propriet virtuali.
Le classi astratte sono lideale nella realizzazione di strutture di base.

Interfacce
Ogni classe realizza uninterfaccia fornendo una struttura (dati e
stato) ed un codice che specifica il funzionamento dei metodi.
C una differenza tra la definizione di uninterfaccia e la sua implementazione. Nella maggior parte dei linguaggi, questa differenza non
netta in quanto la dichiarazione di una classe definisce uninterfaccia
e contemporaneamente la realizza.
Tuttavia, taluni linguaggi presentano caratteristiche che aiutano a
separare la definizione di uninterfaccia dalla sua realizzazione.
Per esempio una classe astratta pu definire uninterfaccia senza implementarla. I linguaggi che supportano leredit tra classi consentono ad una classe di ereditare uninterfaccia da una classe da cui siano derivate.

La metodologia della programmazione orientata agli oggetti


strutturata in modo tale che le operazioni delle varie interfacce di una
classe sono, in genere, indipendenti tra di loro. Il risultato uno
schema stratificato in cui i clienti di un interfaccia utilizzano i metodi
dichiarati nellinterfaccia stessa.
Per esempio i bottoni di un apparecchio televisivo sono linterfaccia
tra lutente e i componenti elettrici ed elettronici contenuti nello chassis. Si preme il bottone power per accendere o spegnere lapparecchio.
Nellesempio, il televisore loggetto ed ogni metodo corrisponde ad
uno dei bottoni che, tutti insieme, rappresentano linterfaccia.
Nella definizione pi comune, uninterfaccia la specificazione di un
gruppo di metodi correlati indipendentemente dalla realizzazione dei

metodi stessi.
Un televisore ha una serie di attributi (le dimensioni, lo schermo al
plasma o a cristalli liquidi etc.) che tutti insieme ne costituiscono la
struttura. Una classe la descrizione completa di un televisore, che
comprende sia i suoi attributi (struttura), che i bottoni
(interfaccia).
In sintesi, linterfaccia definisce la struttura isolandone la realizzazione,
concetto molto utile qualora sia necessario che limplementazione
(realizzazione) sia intercambiabile.
Oltre a ci, uninterfaccia molto utile nel caso che limplementazione cambi frequentemente.
Uninterfaccia pu essere impiegata per definire un modello generico
e una o pi classi astratte che definiscano le realizzazioni parziali del-

linterfaccia. In questo caso, le interfacce si limitano a specificare la


dichiarazione del metodo che, implicitamente pubblico ed astratto e
pu comprendere propriet che sono, sempre implicitamente, pubbliche
ed astratte. Metodi e propriet astratti sono definiti ma non implementati
e, se pubblici, sono accessibili (utilizzabili) da qualsiasi blocco del
programma.
La definizione di uninterfaccia inizia con la parola chiave interfaccia.
Un interfaccia di una classe astratta non pu essere istanziata.
Nel caso che una classe che realizza uninterfaccia non definisca tutti i
metodi dellinterfaccia stessa, allora la classe deve essere dichiarata
astratta e le definizioni dei metodi devono essere fornite dalla sottoclasse che estende la classe astratta.

Oltre a ci un'interfaccia pu ereditare altre interfacce.


Come gi ricordato in precedenza, esistono linguaggi che supportano
varie implementazioni. Il concetto di implementazione implicita ed
esplicita fornisce una maniera sicura per realizzare i metodi di varie
interfacce nascondendo, esponendo o preservando le identit di ciascuno dei metodi delle interfacce anche quando le firme dei metodi
siano le stesse.

Differenze tra una classe ed uninterfaccia


In alcuni linguaggi si pu definire una classe che implementi uninterfaccia e sia anche in grado di supportare pi di unimplementazione. Quando una classe implementa uninterfaccia, un oggetto di tale
classe pu essere incapsulato allinterno di uninterfaccia.
Se MyLogger una classe, che implementa ILogger, allora si pu
scrivere:
ILogger log = new MyLogger();
Concettualmente una classe ed uninterfaccia sono due tipi diversi:
mentre una classe pone laccento sul concetto di incapsulamento, una

interfaccia accentua quello di astrazione, eliminando i dettagli dell'


implementazione. Classe ed interfaccia sono nettamente distinte e di
conseguenza molto difficile o addirittura impossibile confrontarle
in modo significativo.
invece molto utile e significativo osservare analogie e differenze
tra uninterfaccia ed una classe astratta tra le quali, anche se
sembrano simili, c una notevole differenza.

Differenze tra uninterfaccia ed una classe astratta

Interfacce
la definizione di uninterfaccia inizia con la parola
chiave inteUface che ne caratterizza il tipo (interfaccia);
non hanno implementazione ma devono essere implementate;
possono avere solo la dichiarazione, implicitamente
pubblica ed astratta, dei metodi e dati, implicitamente
pubblici e statici;
possono ereditare pi interfacce;
possono essere utili quando limplementazione varia;
rendono le implementazioni intercambiabili;
aumentano la sicurezza mantenendo nascosta limplementazione.

Classi astratte
sono dichiarate per mezzo della parola chiave abstract
che le caratterizza come classi;
i metodi delle classi astratte possono essere implementati e devono essere estesi;
i metodi non possono avere implementazione solo se
sono dichiarati astratti;
possono implementare pi di uninterfaccia ma ereditare da una sola classe;
devono sovrascrivere tutti i metodi astratti e possono
sovrascrivere quelli virtuali;
possono essere utili nella realizzazione di un modello;
possono essere impiegate per fornire un comportamento per default per una classe base;
rappresentano un modo ideale per creare gerarchie di
eredit pianificate ed inoltre sono utilizzabili come termini ultimi nelle gerarchie di classi.

Ereditariet
il processo grazie al quale un oggetto acquista le propriet di un altro oggetto, il che alla base della classificazione gerarchica.
Senza limpiego delle gerarchie, ogni oggetto richiederebbe una dichiarazione esplicita di tutte le sue propriet. Grazie allereditariet,
invece, sufficiente definire solo le caratteristiche delloggetto che lo
rendono unico allinterno della sua classe.
La classe derivata o sottoclasse pu ereditare tutti i suoi attributi generali
dalle classi gerarchicamente superiori da cui deriva.
La creazione di una classe nuova per estensione di una classe gi esistente viene definita ereditariet.

Exception

IOException

public class Exception


{
}

public class IOException extends Exception


{
}
In accordo con lesempio di cui sopra la nuova classe (IOException),
che una classe derivata - o sottoclasse - eredita i membri di una
classe gi esistente (Exception), che una superclasse o classe di base. La classe IOException pu estendere la funzionalit della classe
Exception, aggiungendo tipi e metodi nuovi e sovrascrivendo quelli
preesistenti. Nello stesso modo in cui lastrazione strettamente correlata alla generalizzazione, lereditariet strettamente correlata
alla specializzazione.
Per una miglior comprensione e per ridurre la complessit impor-

tante discutere i due concetti assieme a quello di generalizzazione.


Nel mondo reale una delle pi importanti relazioni tra oggetti la
specializzazione, che pu essere definita come una relazione del tipo
is-a.
Quando si dice che un cane un mammifero si intende che un cane
un tipo specializzato di mammifero. Esso presenta tutte le caratteristiche dei mammiferi (animali vertebrati che respirano aria, a sangue
caldo, con peli, tre ossa nellorecchio interno e ghiandole mammarie
funzionali nelle femmine con prole giovane), ma tali caratteristiche
sono specializzate in quelle ben note del canis domesticus.
Anche un gatto un mammifero e, in quanto tale, ci si aspetta che esso condivida talune caratteristiche del cane, che sono generalizzate
nei mammiferi, ma differisca per quelle caratteristiche che sono spe-

cifiche per i gatti.


Le relazioni di specializzazione e di generalizzazione sono sia reciproche che gerarchiche.
La specializzazione laltra faccia della generalizzazione: i Mammiferi generalizzano ci che comune tra cani e gatti, mentre cani e
gatti specializzano le caratteristiche dei mammiferi nei propri
sottotipi. Analogamente, a titolo di esempio, si pu dire che sia
IOException che SecurityException sono di tipo Exception.
Essi presentano tutte le caratteristiche ed i comportamenti di una Exception. Ci significa che IOException un genere specializzato di
Exception.
Anche una SecurityException una Exception e, in quanto tale, ci si
aspetta che essa condivida con IOException certe caratteristiche che

sono generalizzate in Exception, ma che differisca da essa per le caratteristiche che sono specializzate in SecurityExceptions.
In altri termini, Exception generalizza le caratteristiche comuni a IOException ed a SecurityException, mentre IOException e SecurityException specializzano le proprie caratteristiche ed i propri comportamenti.
In OOP, la relazione di specializzazione implementata tramite il
principio di ereditariet e questo il modo pi diffuso, pi naturale e
pi largamente accettato di realizzare questa relazione.

Polimorfismo
Polimorfis o un termine generico che significa
a molte forme.
i esattam
mente in OOP

si possano avere pi metodi, il che comporta che si possa


progettare uninterfaccia generica per un gruppo di attivit
correlate.
Ci permette di ridurre la compllesssit, utilizzando una sola
interfaccia per specificare una c a
generale di az oni. Sar
compito d l compilatore selezionare
e lazione specifiica, vale a dire il
metodo, pe
er ogni data situazione.
La comprensione dei concetti dellOOP resa meno semplice dal fatto
che essi sono suddivisi in quattro concetti principali ognuno dei quali
strettamente correlato con gli altri. quindi necessario capire
correttamente ogni concetto separatamente, senza perdere di vista il
modo in cui essi sono tra loro correlati.
In OOP il polimorfismo si ottiene grazie a molte differenti tecniche

denominate overloading (sovraccarico) dei metodi, overloading


degli operatori ed overriding (sovrascrittura) dei metodi.

Overloading dei metodi


Loverloading dei metodi consiste nella possibilit di definire diversi metodi con lo stesso nome.
Nei linguaggi fortemente tipizzati a volte desiderabile avere un certo numero di metodi con lo stesso nome, ma che operino su dati di tipo diverso.
Per esempio, una funzione radice quadrata potrebbe essere definita in
modo da poter operare su numeri reali, numeri complessi o su matrici. Lalgoritmo da usare in ciascun caso diverso ed il risultato restituito pu non essere lo stesso.
Scrivendo tre funzioni separate con lo stesso nome il programmatore
ha il vantaggio di non dover ricordare nomi diversi a seconda del tipo
di dati. Inoltre, se si pu definire per i numeri reali un sottotipo che li

suddivida in positivi e negativi, per i reali stessi si possono scrivere


due funzioni, una delle quali restituisce un numero reale quando il parametro positivo e laltra che restituisce un numero complesso
quando il parametro negativo.
Nella programmazione orientata agli oggetti qualora una serie di funzioni o metodi con lo stesso nome possa accettare parametri di tipo
di-verso, si dice che ciascuna delle funzioni sovraccaricata,
overloaded. Per esempio:
public class MyLogger
{
public void LogError(Exception e)
{
// Implementazione
}

public bool LogError(Exception e, string message)


{
// implementazione
}

Overloading degli operatori


Loverloading degli operatori (noto meno comunemente come polymorphism ad hoc) un caso particolare di polimorfismo in cui
uno o pi di una serie di operatori come +, - o == sono trattati come
funzioni polimorfiche e, come tali, hanno comportamenti diversi a seconda del diverso tipo dei loro argomenti.
public class Complex
{
private int real;
public int Real
{ get { return real; } }

private int imaginary;


public int Imaginary
{ get { return imaginary; } }
public Complex(int real, int imaginary)
{
this.real = real;
this.imaginary = imaginary;
}
public static Complex operator +(Complex c1, Complex c2)
{

return new Complex (c1.Real + c2.Real, c1.Imaginary + c2.Imaginary);


}
}
Nellesempio di cui sopra stato sovraccaricato loperatore + per
sommare due numeri complessi. Le due propriet denominate Real ed
Imaginary sono state dichiarate rendendo accessibile solo il metodo
get, mentre il costruttore (constructor) delloggetto richiede valori
obbligatori reali ed immaginari dal costruttore dela classe.
Per esempio:
Complex num1 = new Complex(5, 7);
Complex num2 = new Complex(3, 8);

// sommiamo due numeri complessi usando loverloading di +


Complex sum = num1 + num2;

Overriding dei metodi


Le classi possono essere derivate da una o pi classi esistenti (anche
se non tutti i linguaggi sono in grado di supportare lereditariet
mul-tipla), originando cos una relazione gerarchica tra le classi di
origine (classi basi o classi genitrici o superclassi, superclasses) e le
classi derivate (classi figlie o sottoclassi, subclasses).
La relazione tra queste e quelle nota comunemente come una relazione is - a.
Per esempio la classe 'Button' potrebbe essere derivata dalla classe
'Control'. Quindi, un Button is a Control.
I membri strutturali e comportamentali della superclasse sono
ereditati dalla sottoclasse.
Le classi derivate possono definire membri strutturali (data fields) e/o

membri comportamentali addittivi (metodi) oltre a quelli che esse


ereditano e sono quindi specializzazioni delle relative superclassi.
Ancora, qualora il linguaggio lo permetta, le classi derivate possono
rimpiazzare (override) i metodi ereditati.
Loverriding di un metodo, in OOP, una caratteristica del linguaggio che permette ad una sottoclasse di fornire una realizzazione specifica di un metodo che gi fornito da una delle sue superclassi.
La realizzazione, nella sottoclasse, rimpiazza quella della superclasse
fornendo un metodo che ha lo stesso nome, gli stessi parametri e lo
stesso tipo di risposta di quello della superclasse.
La versione del metodo che sar eseguita sar determinata dalloggetto che usato per invocarla. Se viene usato un oggetto della superclasse verr eseguita la versione del metodo della superclasse stessa,

ma se viene usato un oggetto della sottoclasse allora verr eseguita la


versione della sottoclasse.
Una sottoclasse pu dare la sua propria definizione dei metodi che,
devono per avere la stessa firma che presentano nella superclasse.
Ci significa che il metodo della sottoclasse che viene scritto sopra
quello della superclasse deve avere lo stesso nome e la stessa lista di
parametri di quello della superclasse.
Per esempio:
using System;
public class Complex
{
private int real;
public int Real

{ get { return real; } }


private int imaginary;
public int Imaginary
{ get { return imaginary; } }
public Complex(int real, int imaginary)
{
this.real = real;
this.imaginary = imaginary;
}
public static Complex operator +(Complex c1, Complex c2)

{
return new Complex(c1.Real+ c2.Real, c1.Imaginary +
c2.Imaginary);
}

public override string ToString()


{
return (String.Format("{0} + {1}i", real, imaginary));
}

Nellesempio di cui sopra stata estesa limplementazione delloperatore + nella classe Complex . Questa classe possiede un metodo

sovrascritto denominato ToString, che sovrascrive limplementazione per default del metodo standard ToString per supportare la
corretta conversione in stringa di un numero complesso.
Complex num1 = new Complex(5, 7);
Complex num2 = new Complex(3, 8);
// Somma due numeri complessi utilizzando loperatore +
sovraccaricato
Complex sum = num1 + num2;

// Stampa i numeri e la loro somma utilizzando il metodo ToString


sovrascritto
Console.WriteLine("({0}) + ({1}) = {2}", num1, num2, sum);
Console.ReadLine();

Potrebbero piacerti anche