1. Premessa Qual'è lo scopo della guida e a chi è rivolta 2



Scaricare 238.5 Kb.
Pagina1/4
10.12.2017
Dimensione del file238.5 Kb.
  1   2   3   4

Objects Oriented Programming

Introduzione




1. Premessa
Qual'è lo scopo della guida e a chi è rivolta

2. Introduzione e cenni storici
Cos'è e come è evoluta nel tempo la programmazione "a oggetti"

3. Tecniche di Programmazione
Strategie di programmazione: l'evoluzione fino alla OOP


Concetti Basilari di OOP




4. Rappresentazione della realtà
La programmazione ad oggetti come modello della realtà

5. Metodi e proprietà
le informazioni e le azioni che caratterizzano un oggetto

6. Le Classi
Distinguere tra astratto e concreto: classi e istanze

7. I Messaggi
Stabilire la comunicazione tra gli oggetti

8. Relazioni tra classi
Una applicazione: una piattaforma di classi


I capisaldi della Programmazione ad Oggetti




9. "Pensare" Object Oriented
Introduzione al paradigma Object Oriented

10. L'incapsulamento
Per usare un oggetto non serve sapere come è fatto

11. L'ereditarietà
Dall'estensione dei concetti alla riusabilità.

12. Il polimorfismo
Azioni diverse associate ad un solo metodo.

13. L'astrazione
Cosa sono e a cosa servono metodi e classi astratte

14. La visibilità (1a parte)
Contesti di visibilità (scope) di metodi e proprietà

15. La visibilità (2a parte)
Il ruolo della visibilità nei rapporti tra classi


Nozioni avanzate




16. Il singleton
Creare un'unica istanza della classe in un programma

17. L'Ereditarietà multipla
Riusare aspetti diversi da classi diverse

18. Le Interfacce
L'alternativa all'ereditarità multipla


Principi di progettazione




19. Coesione e accoppiamento
Dimensionare opportunamente le classi

20. Il Processo di sviluppo in OOP
Un cenno alla OOD (Object Oriented Design)

1. Premessa

Lo scopo principale di questa guida è quello di fornire una panoramica sulla tecnica di programmazione più diffusa e consolidata nel mondo dello sviluppo applicativo: La Programmazione ad Oggetti (Object Oriented Programming, da cui l'acronimo OOP, che utilizzeremo frequentemente nel corso della guida).

Non si richiedono particolari conoscenze pregresse nel mondo della programmazione per poter leggere le pagine che seguono, in quanto gli argomenti trattati vengono esaminati partendo da nozioni decisamente basilari.

Pertanto la guida è rivolta sia a coloro che non hanno mai utilizzato alcun linguaggio di programmazione "ad Oggetti" sia a coloro che hanno già conoscenza o esperienza in tale settore. Questi ultimi potranno approfittare della guida per chiarire meglio alcuni concetti che spesso vengono fraintesi o che sono talvolta fonte di confusione.

Una cosa importante da non trascurare per i tanti programmatori con conoscenza di linguaggi procedurali come il Visual Basic (fino alla versione 6.0, per lo meno) è di evitare fortemente di utilizzare il modus operandi e le regole implementative apprese con tale linguaggio, in quanto potrebbero rendere più arduo l'apprendimento dei concetti che governano il mondo della programmazione ad oggetti.

2. Introduzione e cenni storici

La Programmazione ad Oggetti rappresenta, senza dubbio, il modello di programmazione più diffuso ed utilizzato degli ultimi dieci anni.

Le vecchie metodologie come la programmazione strutturata e procedurale, in auge negli anni settanta, sono state lentamente ma inesorabilmente superate a causa degli innumerevoli vantaggi che sono derivati dall'utilizzo del nuovo paradigma di sviluppo.

Un esempio, ben noto a tanti programmatori, è rappresentato dalla profonda trasformazione che ha subito il Visual Basic nell'ultima versione rilasciata dalla Microsoft (Visual Basic .NET) che lo vede finalmente catalogato come un linguaggio ad Oggetti a tutti gli effetti.

Eppure, contrariamente a quanto si possa pensare, le origini della Programmazione ad Oggetti sono abbastanza remote: i primi linguaggi "ad oggetti" furono il SIMULA I e il SIMULA 67, sviluppati da Ole-Johan Dahl e Kristen Nygaard nei primi anni '60 presso il Norwegian Computing Center.

Entrambi questi linguaggi adottavano già parecchie delle peculiarità che sono oggi tra i capisaldi della programmazione ad oggetti, come ad esempio le classi, le sottoclassi e le funzioni virtuali ma, a dispetto dell'importanza storica, tali linguaggi non riscossero particolare successo.

Negli anni '70 fu introdotto il linguaggio SmallTalk, coinsiderato da molti il primo vero linguaggio ad oggetti "puro". Lo SmallTalk fu sviluppato in due periodi successivi: inizialmente da Alan Kay, ricercatore dell'università dello Utah e successivamente fu ripreso da Adele Goldberg e Daniel Ingalls, entrambi ricercatori allo Xerox Park di Palo Alto, in California.

Ma, ancora una volta, il grande successo tardò ad arrivare. Probabilmente, la ragione di ciò era da ricercare nel fatto che questo linguaggio (come il Simula) era considerato, per lo più, uno strumento destinato alla ricerca e allo studio più che allo sviluppo.

A questo si aggiunga che negli anni '70 il linguaggio C riscuoteva enorme successo grazie alle sue potenzialità e, soprattutto, al fatto che il famoso sistema operativo Unix (ancora oggi fortemente usato) fosse stato scritto utilizzando proprio tale linguaggio.

Fu, insomma, necessario attendere gli anni '80 con l'avvento del linguaggio ADA per assistere alla definitiva consacrazione della programmazione ad oggetti come modello da utilizzare. Probabilmente la vera svolta fu rappresentata dall'avvento del C++, creato da Bjarne Stroustrup.

Tra i più noti linguaggi di programmazione ad oggetti, citiamo il C++, Java, Delphi, C# e, come detto, il Visual Basic .NET.

3. Tecniche di Programmazione

Si è precedetemente accennato a "vecchie" metodologie di programmazione e a come queste siano state lentamente ma inesorabilmente messe da parte con la diffusione dell'OOP. In questa lezione verranno descritte brevemente tali metodologie al fine di comprendere meglio le differenze con la programmazione ad oggetti.




Programmazione Non Strutturata

Con la programmazione strutturata il programma è costituito da un unico blocco di codice detto "main" dentro il quale vengono manipolati i dati in maniera totalmente sequenziale.

È importante notare che tutti i dati sono rappresentati soltanto da variabili di tipo globale, ovvero visibili da ogni parte del programma ed allocate in memoria per tutto il tempo che il programma stesso rimane in esecuzione.

È facile capire che un simile contesto è fortemente limitato e pieno di svantaggi. Ad esempio, sarà facile incappare in spezzoni di codice ridondanti o ripetuti che non faranno altro che rendere presto ingestibile ed "illeggibile" il codice, causando oltretutto un enorme spreco di risorse di sistema.

Nella figura seguente, viene rappresentata graficamente l'architettura di questo tipo di paradigma di sviluppo.

Figura 1. Schema della programmazione non strutturata


Programmazione Procedurale

Un notevole passo in avanti, rispetto alla Programmazione Non Strutturata, venne fatto con l'avvento della Programmazione Procedurale. I programmatori in Visual Basic 5.0 o 6.0 sapranno certamente di cosa si sta parlando (anche se il Visual Basic utilizza anche il paradigma di Programmazione Modulare, descritta nel successivo paragrafo).

Il concetto base qui è quello di raggruppare i pezzi di programma ripetuti in porzioni di codice utilizzabili e richiamabili ogni volta che se ne presenti l'esigenza: nascevano le Procedure.

Ogni procedura può essere vista come un sottoprogramma che svolge una ben determinata funzione (ad esempio, il calcolo della radice quadrata di un numero) e che è visibile e richiamabile dal resto del codice.

Inoltre ogni procedura ha la capacità di poter utilizzare uno o più parametri che ne consentono una maggiore duttilità. Anche il flusso del programma è decisamente diverso rispetto a quello visto nella programmazione non strutturata: infatti, il main continua ad esistere ma al suo interno appaiono soltanto le invocazioni alle procedure definite nel programma.

Quando una procedura ha terminato il suo compito il controllo ritorna nuovamente al main (o alla procedura che ne ha effettuato l'invocazione) che esegue una nuova chiamata ad un'altra procedura. fino alla terminazione del programma. Un semplice schema puo' facilitare la comprensione di tale concetto:



Figura 2. Flusso di un programma con programmazione procedurale

Il grande vantaggio della programmazione procedurale, rispetto alla precedente non strutturata consiste in un notevole abbattimento del numero di errori, che deriva dal fatto che se una procedura è corretta allora vi è la certezza che essa restituirà ad ogni invocazione dei risultati corretti in output.




Programmazione Modulare

La programmazione modulare rappresenta un' ulteriore conquista. Sorgeva l'esigenza di poter riutilizzare le procedure messe a disposizione da un programma in modo che anche altri programmi ne potessero trarre vantaggio.

Così, l'idea fu quella di raggruppare le procedure aventi un dominio comune (ad esempio, procedure che eseguissero operazioni matematiche) in moduli separati.

Quando sentiamo parlare di librerie di programmi, in sostanza si fa riferimento proprio a moduli di codice indipendenti che ben si prestano ad essere inglobati in svariati programmi.



Figura 3. Struttura di un programma «modulare»

Il risultato, dunque, adesso è che un singolo programma non è più costituito da un solo file (in cui è presente il main e tutte le procedure) ma da diversi moduli (uno per il main e tanti altri quanti sono i moduli a cui il programma fa riferimento).

È importante, inoltre, dire che i singoli moduli possono contenere anche dei dati propri che, in congiunzione ai dati del main, vengono utilizzati all'interno delle procedure in essi contenute. Graficamente potremmo riassumere il tutto nel seguente modo:


Programmazione ad Oggetti

La programmazione procedurale/modulare ha rappresentato il punto di riferimento nello sviluppo applicativo per tanti anni. Gradualmente ma inevitabilmente però, man mano che gli orizzonti della programmazione diventavano sempre più ampi, si andarono evidenziando i limiti di tale metodologia.

In particolare, un programma procedurale mal si prestava a realizzare il concetto di "Componente Software", ovvero di un prodotto in grado di garantire le caratteristiche di riusabilità, modificabilità e manutenibilità.

Una delle cause di tale limite è da ricercare sicuramente nel fatto che esiste un evidente scollamento tra i dati e le strutture di controllo che agiscono su di essi; in altre parole i moduli risultano avere un approccio orientato alla procedura piuttosto che ai dati.

Con l'avvento della programmazione ad oggetti (i cui concetti saranno dettagliati a partire dal prossimo capitolo) questi limiti vennero superati. Contrariamente alle tecniche fin qui descritte, il paradigma OOP è basato sul fatto che esiste una serie di oggetti che interagiscono vicendevolmente, scambiandosi messaggi ma mantenendo ognuno il proprio stato ed i propri dati. Graficamente:

Figura 4. Colloquio tra oggetti

La programmazione ad oggetti, naturalmente, pur cambiando radicalmente l'approccio mentale all'analisi progettuale non ha fatto a meno dei vantaggi derivanti dall'uso dei moduli. Al contrario, tale tecnica è stata ulteriormente raffinata avvalendosi delle potenzialità offerte dalla programmazione ad oggetti.



4. Rappresentazione della realtà

L'idea principale che sta dietro la Programmazione ad Oggetti risiede, in buona parte, nel mondo reale. Come spesso accade, gli esempi pratici forniscono una comprensione più chiara ed immediata della teoria e, pertanto, si userà tale approccio per fissare bene in mente i concetti basilari del mondo OOP.

Si prenda in considerazione un comune masterizzatore, come quelli ormai diffusi nella stragrande maggioranza dei moderni PC. Di tale oggetto si conoscono le sue caratteristiche ma quasi nessuno (se non coloro che lo hanno progettato e assemblato) è a conoscenza dei componenti elettronici e dei sofisticati meccanismi che ne regolano il corretto funzionamento, ne' a qualcuno salterebbe in mente di smontare un masterizzatore prima di acquistarlo per vedere come è fatto all'interno (supposto che il negoziante sia disposto ad accettare una tale richiesta, decisamente fuori dal comune!).

Il concetto che sta dietro alla programmazione ad oggetti nasce dallo stesso principio: ciò che importa non è l'implementazione interna del codice (che corrisponde ai componenti elettronici, nel caso del masterizzatore) ma, piuttosto, le caratteristiche e le azioni che un componente software è in grado di svolgere e che mette a disposizione (espone) all'esterno.

Dunque, con riferimento a quanto gia detto in precedenza, un programma che segue il paradigma OOP è costituito da un numero variabile di tali componenti, che ora denominiamo oggetti, i quali interagiscono tra di essi attraverso lo scambio di messaggi.

Proseguendo nell'esempio del masterizzatore e supponendo di voler implementare un oggetto software che ne gestisca le funzionalità, potremmo iniziare a definirne le caratteristiche. Ad esempio:



  • Marca

  • Velocità di scrittura su supporti CD-R

  • Velocità di scrittura su supporti CD-RW

  • Velocità di lettura

  • Interfaccia

  • Dimensione del buffer dati

Mentre, per quanto riguarda le azioni potremmo considerare le seguenti:

  • Scrivi su CD

  • Scrivi su DVD

  • Leggi CD

  • Espelli CD

In parole molto semplici, potremmo dire che le azioni altro non sono che "le cose che un oggetto è in grado di fare" mentre le sue caratteristiche rappresentano i dati che le azioni stesse possono utilizzare per eseguire le operazioni che da esse ci si aspetta.

In OOP, le caratteristiche di un oggetto vengono denominate proprietà e le azioni sono dette metodi. Questi sono due concetti fondamentali ed è molto importante che siano ben chiari prima di introdurre nuove definizioni.

Altrettanto importante, però, è ribadire il contesto in cui abbiamo iniziato a ragionare: non dobbiamo pensare più ad un programma che racchiuda tutto in un unico grande calderone ma dobbiamo iniziare a pensare "ad oggetti". Dobbiamo, cioè, essere in grado di identificare gli oggetti che entrano in gioco nel programma che vogliamo sviluppare e saperne gestire l'interazione degli uni con gli altri.

In un programma di tipo procedurale, si è soliti iniziare a ragionare in maniera top-down, partendo cioè dal main e creando mano a mano tutte le procedure necessarie. Tutto questo non ha più senso nella programmazione ad oggetti, dove serve invece definire prima le classi e poi associare ad esse le proprietà ed i metodi opportuni.

Nella guida UML, si fa riferimento (dove si parla del Rapid Application Development) al metodo utilizzato durante l'analisi progettuale per identificare in modo ottimale le classi da utilizzare.

5. Metodi e proprietà

I metodi: le azioni che un oggetto è in grado di compiere

Come detto, un metodo rappresenta una azione che può essere compiuta da un oggetto. Una delle domande principali da porsi quando si vuole creare un oggetto è: "Cosa si vuole che sia in grado di fare?".

In effetti, quando ci si pone questa domanda, si sta involontariamente dando per buono il fatto che qualsiasi oggetto sia in qualche modo capace di eseguire delle azioni, trattandolo come se avesse natura umana. Eppure, anche se inizialmente può apparire quantomeno curioso e insolito, questo approccio rappresenta un importante riferimento nella fase di disegno e creazione degli oggetti.

In generale, potremmo delineare almeno tre buone regole per identificare i metodi da associare ad un oggetto:



  1. Un oggetto che abbia uno o due soli metodi deve fare riflettere. Potrebbe essere perfettamente lecito definire un oggetto del genere (ed è sicuramente possibile farlo praticamente) ma, spesso, un oggetto creato con questi requisiti indica la necessità di "mescolarlo" con un altro oggetto con simile definizione.

  2. Ancora più da evitare sono gli oggetti con nessun metodo. È bene che un oggetto incapsuli (vedremo meglio in seguito cosa si intenda con tale terminologia) dentro sé sia informazioni (le proprietà), sia azioni (i metodi, appunto). In linea di massima, un oggetto senza metodi può facilmente essere convertito in uno o più attributi da assegnare ad un altro oggetto.

  3. Sicuramente da evitare sono anche gli oggetti con troppi metodi. Un oggetto, in generale, dovrebbe avere un insieme facilmente gestibile di proprie responsabilità. Assegnare ad un oggetto troppe azioni, potrebbe rendere ardua la manutenzione futura dello stesso oggetto. È consigliabile, in questo caso, cercare di spezzare l'oggetto in due oggetti più piccoli e semplificati.


Le proprietà: informazioni su cui opera un oggetto

Le proprietà rappresentano i dati dell'oggetto, ovvero le informazioni su cui i metodi possono eseguire le loro elaborazioni.



Uno degli errori più comuni che si commette quando si definiscono le proprietà di un oggetto è quello di associare ad esso quante più proprietà possibili, ritenendo che questo possa, in qualche modo, facilitare la stesura del programma. Un oggetto, invece, per essere ben definito deve contenere le proprietà che, effettivamente, gli competono e non tutte quelle che gli si potrebbero comunque attribuire.

Questa regola di buona programmazione nasce, oltretutto, dall'esigenza di rendere più facile la fase di disegno e quella di debug che altrimenti risulterebbero certamente complesse.

Per evitare, dunque, l'inconveniente di ritrovarsi dei super-oggetti sarà bene porsi la seguente domanda nella fase di definizione: «quali proprietà sono necessarie affinché l'oggetto sia in grado di eseguire le proprie azioni?»

In generale, esistono tre tipologie di proprietà: gli attributi, i componenti e i peer objects.



Gli attributi rappresentano quelle proprietà che descrivono le caratteristiche peculiari di un oggetto (ad esempio, riferendoci ad una persona: altezza, peso).

I componenti, invece, sono identificabili in quelle proprietà che sono atte a svolgere delle azioni (testa, corpo, mani, gambe).

Infine, i peer objects definiscono delle proprietà che a loro volta sono identificate e definite in altri oggetti (ad esempio: l'automobile posseduta da una persona).



6. Le Classi

Probabilmente, il termine più importante e rappresentativo nella Programmazione ad Oggetti è quello di Classe.

Riprendiamo ancora l'esempio del masterizzatore. Sappiamo benissimo che non esiste un solo tipo di masterizzatore ma, a secondo delle caratteristiche, è possibile citarne tanti modelli: ci sono, ad esempio, quelli in grado di scrivere su CD e DVD o quelli che scrivono solo su CD.

Sicuramente, però, tutti sono in grado di eseguire la scrittura di dati o file multimediali su CD e tutti hanno, altresì, le proprietà esposte nelle lezioni precedenti.

Diremo allora che più oggetti software che hanno le stesse proprietà e gli stessi metodi possono essere raggruppati in una classe ben definita di oggetti: nel nostro caso particolare, nella classe masterizzatore.

Dunque, una classe rappresenta, sostanzialmente, una categoria particolare di oggetti e, dal punto di vista della programmazione, è anche possibile affermare che una classe funge da tipo per un determinato oggetto ad essa appartenente (dove con tipo si intende il tipo di dato, come lo sono gli interi o le stringhe).

Diremo, inoltre, che un particolare oggetto che appartiene ad una classe costituisce un'istanza della classe stessa. In altre parole, un'istanza della classe masterizzatore sarà costituita da un oggetto di tale classe che è in grado di scrivere solo su CD mentre un'altra istanza potrà essere rappresentata da un oggetto che è in grado di masterizzare anche i DVD.

È anche possibile creare due o più istanze separate di oggetti uguali (sarebbe meglio dire di oggetti che hanno le proprietà valorizzate allo stesso modo) ma ciò non vorrà dire che in un determinato istante nel corso del programma tutte queste istanze eseguano la medesima operazione o che, in generale, siano necessariamente correlati.

L'univocità di ogni istanza viene definita con il termine di identità (identity): ogni oggetto ha una propria identità ben distinta da quella di tutte le altre possibili istanze della stessa classe a cui appartiene l'oggetto stesso.

Naturalmente, le proprietà di un oggetto possono avere valori che variano nel tempo. Ad esempio, la velocità di scrittura potrebbe essere selezionata dall'utente e, pertanto, potrebbe variare nel corso del programma. Si definisce stato di un oggetto, l'insieme dei valori delle sue proprietà in un determinato istante di tempo. Se cambia anche una sola proprietà di un oggetto, il suo stato varierà di conseguenza.

L'insieme dei metodi che un oggetto è in grado di eseguire viene definito, invece, comportamento (behavior). Insomma, appare sempre più chiaro come un oggetto rappresenti un'entità a sé stante, ben definita che, nel corso dell'elaborazione, sia soggetta ad una creazione, ad un suo utilizzo e, infine, alla sua distruzione.

Inoltre, un oggetto non dovrebbe mai manipolare direttamente i dati interni (le proprietà) di un altro oggetto ma ogni tipo di comunicazione tra oggetti dovrebbe essere sempre gestita tramite l'uso di messaggi, ovvero tramite le chiamate ai metodi che un oggetto espone all'esterno.



elenco: users -> corsini
users -> 1. Definizione di Albero
users -> L’insieme delle tecniche e degli strumenti che IL docente adotta in classe
users -> Osservazioni Botaniche Vegetazione spontanea arboreo-arbustiva alla testa e lungo l’asta del Fontanile
users -> La montagna incantata, IL Purgatorio di Dante e IL pellegrino–viator alla rovescia, cioè lo statico residente Hans Castorp
users -> La geografia (giochi di tragitti, di percorsi, di territori e confini, cacce al tesoro, idee di distanze, di lunghezze) La psicomotricità
users -> Una possibile sequenza di attività (anche di tipo ludico) su questo tema può essere la seguente, sperimentata in una classe 5
users -> Le indagini più recenti del Ministero dell’Istruzione sui dati della dispersione scolastica arrivano a concludere che la dispe
users -> Lezione 2 L'italiano d'oggi: le varietà funzionali, situazionali e strutturali
users -> Distinguiamo tra dimostrazione ed argomentazione; la prima ha carattere di certezza e di incontrovertibilità è usata nella ri
corsini -> Per biomassa si intende ogni sostanza organica prodotta dalla fotosintesi; costituisce un serbatoio di energia solare che si riproduce con continuità e nei tempi brevi dei cicli biologici, per questo può, a tutti gli effetti


Condividi con i tuoi amici:
  1   2   3   4


©astratto.info 2019
invia messaggio

    Pagina principale