Sei sulla pagina 1di 70

Fondamenti di programmazione ad oggetti

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

Lapproccio della programmazione orientata agli oggetti, OOP, invece, fa s che il programmatore localizzi i dati dove non siano direttamente accessibili dal resto del programma. Ai dati stessi si pu ac-cedere chiamando (invocando) 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 ricuperare o modificare i dati che esse 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 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 di un sistema (e cio del linguaggio informatico relativo) e la definizione dei suoi requisiti non funzionali, di quelle qualit cio che sono relative a ci che esso e non a ci che fa (requisiti funzionali). Sono requisiti non funzionali quelli osservabili a run time, come per esempio la sicurezza e la facilit di utilizzo, e quelli incorporati nella struttura statica del sistema come, per 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); d 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 i programmatori 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 (e.g, un oggetto pu ereditare le caratteristiche di un altro). Uno dei principali vantaggi delle tecniche OOP, rispetto alle tecniche procedurali, consiste nel fatto che esse mettono in grado i program-matori 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 specie particolare di dati complessi da gestire, oppure ad un oggetto od un concetto del mon-do reale, come per esempio un conto corrente postale, un calciatore o una macchina per il movimento terra. 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 incartati in una serie di funzioni progettate per far s che tali dati siano usati in modo appropriato e sia reso pi facile il loro impiego. 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 delle quali (oggetto classe) contiene tutte le informa zioni 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, Incapsulazione, Ereditariet e Polimorfismo.

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

2. stato: descrizione dei dati (propriet) immagazzinati nelloggetto; 3. comportamento: descrizione dei metodi associati alloggetto che consentono il suo impiego. 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. In ogni momento 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 ed 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 oggetti semplicemente). 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 oggetti individuali

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 che 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 dividi 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 raggruppate 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 liguaggi 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 (e.g. automobile) has a un oggetto di tipo pi semplice (e..g. 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 Carburetor

aggregazione:

Pond

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 (e.g., chimica, 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 diffrenza 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 qualche principiante 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, e che spesso viene dimenticato quello relativo alla durata di vita. Le durate di vita di due classi, che siano legate da una relazione di composizione sono interdipendenti.
Academy
- academySecretary : Secretary

Course
- name : string

<<property>> + academySecretary () : Secretary

Secretary
- name : string

Nel caso che non esista interdipendenza tra le durate di vita allora la relazione sar di tipo aggregazione piuttosto che di tipo composizione Se se si vuole pertanto che due classi siano legate da una relazione di composizione, il modo migliore per realizzare 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 la 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 nella costruzione di programmi, 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 che nuovo per essa 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. Oltre a ci 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 disegnata 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 spinge 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 tutta una serie di attributi, quali le dimensioni, lo schermo al plasma o a cristalli liquidi ..., 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 sono pubblici sono accessibili (visibili) 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, un

interfaccia accentua quello di astrazione eliminando i dettagli della implementazione. Classe ed interfaccia sono nettamente distinte tra di loro e di conseguenza molto difficile o addirittura impossibile confrontarle in modo significativo. invece sia molto utile che 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 inte-face 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 quelle caratteristiche delloggetto che lo rendono unico allinterno della sua classe. Loggetto (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 Polimorfismo un termine generico che significa molte forme. Pi esattamente in OOP Polymorphism intende la capacit che le stesse operazioni siano realizzate da unampia gamma di differenti tipi di entit. Un operazione pu mostrare comportamenti diversi in diverse istanze a seconda dei tipi di dati utilizzati nelloperazione. Questa caratteristica consente di usare la stessa interfaccia per una classe generale di azioni. Lazione specifica determinata dalla natura esatta della situazione. Quindi in generale il polimorfismo implica che per uninterfaccia

si possano avere pi metodi il che implica che si pu progettare uninterfaccia generica per un gruppo di attivit correlate. Ci permette di ridurre la complessit utilizzando una sola interfaccia per specificare una classe generale di azioni. Sar compito del compilatore selezionare lazione specifica, vale a dire il metodo, per 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, metodi, con lo stesso nome possa accettare parametri di tipo diverso 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 polymorphism 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 multipla), 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