mercoledì 22 novembre 2006

ProGrammaZione OrienTata Agli oGgetti...

La programmazione orientata agli oggetti (OOP, Object Oriented Programming) è un paradigma di programmazione, che prevede di raggruppare in un'unica entità (la classe) sia le strutture dati che le procedure che operano su di esse, creando per l'appunto un "oggetto" software dotato di proprietà (dati) e metodi (procedure) che operano sui dati dell'oggetto stesso.
Oggetti
Un oggetto è una istanza di una classe. Un oggetto occupa memoria, la sua classe definisce come sono organizzati i dati in questa memoria.
Ogni oggetto possiede tutti gli attributi definiti nella classe, ed essi hanno un valore, che può mutare durante l'esecuzione del programma come quello di qualsiasi variabile. Il paradigma OOP suggerisce un principio noto come information hiding che indica che si debba accedere agli attributi dell'istanza solo tramite metodi invocati su quello stesso oggetto.
Sintatticamente, i metodi di una classe vengono invocati "su" un particolare oggetto, e ricevono come parametro implicito l'oggetto su cui sono stati invocati. Questo parametro normalmente può essere referenziato esplicitamente; per esempio, a tale scopo in C++, in Java, e in C# si usa la parola chiave this, mentre in Smalltalk, in Objective-C, Python e in Ruby si usa la parola-chiave self.
Gli oggetti effettivamente creati sono membri dell'insieme definito dalla loro classe.
Molti linguaggi forniscono un supporto per l'inizializzazione automatica di un oggetto, con uno o più speciali metodi detti costruttori. Analogamente, la fine della vita di un oggetto può essere gestita con un metodo detto distruttore.
Incapsulamento
L'incapsulamento è la proprietà per cui un oggetto contiene ("incapsula") al suo interno gli attributi (dati) e i metodi (procedure) che accedono ai dati stessi. Lo scopo principale dell'incapsulamento è appunto dare accesso ai dati incapsulati solo attraverso i metodi definiti, nell'interfaccia, come accessibili dall'esterno. Gestito in maniera intelligente, l'incapsulamento permette di vedere l'oggetto come una black-box, cioè una scatola nera di cui, attraverso l'Interfaccia sappiamo cosa fa e come interagisce con l'esterno ma non come lo fa . Il vantaggi principali portati dall'incapsulamento sono: robustezza, indipendenza e l'estrema riusabilità degli oggetti creati.
Ereditarietà
L'OOP prevede un meccanismo molto importante, l'ereditarietà, che permette di derivare nuove classi a partire da classi già definite. L'ereditarietà permette di aggiungere membri ad una classe, e di modificare il comportamento dei metodi, in modo da adattarli alla nuova struttura della classe.
Da una stessa classe è possibile costruire diverse classi derivate. Da una classe derivata è possibile derivarne un'altra con lo stesso meccanismo.
Sintatticamente, una classe può essere definita come derivata da un'altra classe esistente. In molti linguaggi la classe derivata, o sottoclasse, eredita tutti i metodi e gli attributi della classe "genitrice", e può aggiungere membri alla classe, sia attributi che metodi, e/o ridefinire il codice di alcuni metodi.
L'ereditarietà può essere usata come meccanismo per gestire l'evoluzione ed il riuso del software: il codice disponibile definisce delle classi, se sono necessarie modifiche, vengono definite delle sottoclassi che adattano la classe esistente alle nuove esigenze.
Polimorfismo
La possibilità che le classi derivate implementino in modo differente i metodi e le proprietà dei propri antenati rende possibile che gli oggetti appartenenti a delle sottoclassi di una stessa classe rispondano diversamente alle stesse istruzioni. Ad esempio in una gerarchia in cui le classi Cane e Gatto discendono dalla SuperClasse Animale potremmo avere il metodo mangia() che restituisce la stringa "osso" se eseguito sulla classe Cane e "pesce" se eseguito sulla classe Gatto. I metodi che vengono ridefiniti in una sottoclasse sono detti "polimorfi", in quanto lo stesso metodo si comporta diversamente a seconda del tipo di oggetto su cui è invocato.
In linguaggi in cui le variabili non hanno tipo, come Ruby, Python e Smalltalk è possibile richiamare un qualsiasi metodo su di un qualsiasi oggetto, quindi il polimorfismo è molto più esteso, sebbene ciò comporti la possibilità di errori a runtime. Tali errori sono eliminabili da linguaggi puramente statici, ma ciò è possibile solamente riducendone l'espressività oppure accettando dei buchi nel type system (i NullPointerException di Java, ad esempio).
Le buone regole di programmazione ad oggetti prevedono che quando una classe derivata ridefinisce un metodo, il nuovo metodo abbia la stessa semantica di quello ridefinito, dal punto di vista degli utenti della classe.Il polimorfismo è particolarmente utile quando la versione del metodo da eseguire viene scelta sulla base del tipo di oggetto effettivamente contenuto in una variabile a runtime (invece che al momento della compilazione). Questa funzionalità è detta binding dinamico (o late-binding), e richiede un grosso sforzo di supporto da parte della libreria runtime del linguaggio.

Nessun commento: