Paradigmi di programmazione

In parallelo con i linguaggi di programmazione, si sono sviluppati vari paradigmi di programmazione:
  • Programmazione imperativa
  • Programmazione dichiarativa (funzionale, logica, algebrica)
  • Programmazione orientata ad oggetti (Object Oriented programming)

Normalmente un linguaggio fornisce costrutti e meccanismi per programmare in uno o più di questi paradigmi. Ad esempio:

Pascal, Fortran, Cobol, C
Imperativo
ML, Lisp, Haskell, Scheme
Dichiarativo (funzionale)
Prolog
Dichiarativo (logico)
Smalltalk
OO
C#, C++, Java, Delphi
Imperativo + OO
Clos, Zeta-Lisp
Funzionale + OO

Tale suddivisone non è rigida: ad esempio, le versioni iniziali del sistema operativo del Macintosh furono scritte in Pascal, ma in stile OO




La programmazione imperativa

Nel primo modulo di LIP abbiamo studiato il frammento imperativo di Java, cioè i costrutti che Java fornisce per scrivere programmi secondo il paradigma imperativo.

Nella programmazione imperativa, l'enfasi viene posta nella progettazione e nella scrittura dell'algoritmo con il quale, a partire dai dati in ingresso, si producono i risultati.

Una computazione si svolge come una sequenza di cambiamenti di stato, come visto anche nella semantica operazionale presentata a FP. Lo stato viene modificato da comandi semplici (assegnamento, invocazione di metodo), che possono essere combinati usando istruzioni condizionali o iterative.

Quindi l'enfasi è posta sulle strutture di controllo: i dati (elementari o strutturati, come gli array) sono manipolati in modo passivo.




La programmazione
orientata ad oggetti

Nella programmazione orientata ad oggetti, l'enfasi viene posta nella progettazione di un modello del dominio di applicazione. Un oggetto è una rappresentazione di un oggetto del mondo reale, o di un concetto.

Nella fase di progettazione si individuano gli oggetti rilevanti, e per ogni oggetto si identifica la sua struttura e le sue funzionalità. Ogni oggetto ha un proprio stato, e gli oggetti interagiscono quando un oggetto attiva una funzionalità di un altro oggetto. L'effetto che ne consegue può essere un cambio di stato, la creazione di altri oggetti, la attivazione di altre funzionalità dello stesso oggetto o di altri oggetti.

Gli oggetti sono raggruppati in classi: ogni classe rappresenta un insieme di oggetti simili per struttura e funzionalità. La relazione di sottoinsieme viene modellata con la relazione di ereditarietà tra le classi.


Una computazione si sviluppa come una sequenza di attivazioni di funzionalità di oggetti.




Programmazione OO in Java

Java fornisce costrutti per realizzare tutti i concetti menzionati:
oggetti
istanze di classe (instances)
classi
classi (classes)
struttura
  variabili di istanza (instance variables
funzionalità
metodi (methods)
  attivazione di funzionalità 
chiamata di metodo (method call)
creazione di oggetti
primitiva new
ereditarietà
relazione extends