![]() | ![]() |
|
|
Perchè la programmazione ad oggetti?
L'attività del
programmatore
Possiamo considerare l'attività del programmatore come quella di un ingegnere
che costruisce un ponte. La cosa più importante e' che il ponte non crolli,
ovvero che il programma funzioni. La programmazione a oggetti permette di
costruire ponti che non crollano? Ahime no! Qualsiasi tecnica di costruzione
programmi usiamo niente ci garantisce il successo del programma. Questo e'
dovuto solo all'abilità del programmatore. Allora a cosa serve la programmazione
ad oggetti? Bene, se siamo riusciti a costruire un programma funzionante in
qualche mod 828g68i o, come seconda cosa importante , vorremmo che il programma sia di
facile manutenzione. Infine vorremmo poterlo usare per costruire "altri
ponti che non cadono". Ora la vecchia tecnica funzionale (programma
=struttura di dati +funzioni) permette di costruire programmi
"monolitici" di difficile manutenzione e riuso. La programmazione a
oggetti invece spezzando il programma in tanti oggetti indipendenti dovrebbe
facilitare queste operazioni. L'unica struttura di dati e libreria di funzioni
del programma funzionale si e'
trasformata in una serie di oggetti ognuno dei quali ha una propria struttura
di dati e una libreria di funzioni. Come si vede un programma ad oggetti e' un'ulteriore astrazione del programma funzionale che potrebbe essere considerato
come un programma a un solo oggetto. Per tornare alla nostra metafora
ingegnieristica, ora stiamo costruendo ponti con moduli prefabbricati in modo
da rendere più facile la costruzione di altri ponti simili.
I linguaggi ad
oggetti: un'ulteriore astrazione Ora i dati sono racchiusi assieme
alle funzioni negli oggetti: questa e' l'ulteriore astrazione introdotta dai
linguaggi a oggetti. E, come vedremo, i dati sono accessibili solo attraverso
speciali funzioni.
La struttura di dati che descrive lo stato di un oggetto viene definita ora
dalle proprietà dell'oggetto e
realizzata con le variabili
dell'oggetto. (Queste sono chiamate talvolta anche campi fields in inglese).
Mentre le funzioni che descrivono il comportamento dell'oggetto diventano i metodi dello stesso. La classe e' un pezzo di codice che
descrive le proprieta' e i metodi di un oggetto. Per cui ora un programma e' formato da una serie di
classi. Si dice anche che metodi e variabili sono membri della classe(in C++ infatti variabili e metodi si chiamano data members e member functions).
I linguaggi ad oggetto hanno particolari costrutti che permettono di trattare
gli stessi oggetti.I n particolare l'operatore new permette di creare un oggetto descritto in una classe o come si
dice di instanziare lo stesso o
crearne una istanza. Questo
corrisponde in pratica alla chiamata di un particolare metodo il costruttore che ha lo stesso nome
della classe e che provvede a inizializzare la struttura di dati
dell'oggetto(in effetti secondo i puristi il costruttore non e' un metodo ).
L'accesso a una particolare proprietà o metodo di un oggetto avviene attraverso
l'operatore ".":nomeoggetto.nomeproprieta
e nomeoggetto.nomemetodo().I due
riferimenti si distinguono solo per la presenza delle parentesi tonde per i
metodi.
Un caso concreto
Volendo costruire un programma che tratti eventi della fisica delle alte
energie con le loro tracce e i loro run, nel caso della programmazione
funzionale costruiremmo una struttura di dati contenente Evento Traccia e Run più una libreria di funzioni che
fanno diverse operazioni su questi dati. (Da notare che il nome funzione qui
indica la stessa cosa di procedura, routine, sottoprogramma).
Nella programmazione a oggetti partiremmo subito dai 3 oggetti Traccia, Evento e Run e per ogni
oggetto definiremmo quindi le proprietà e il comportamento. Le funzioni
dell'approccio procedurale appaiono ora come metodi all'interno delle classi.
Un programma utente ora invece di richiamare una serie di funzioni per
manipolare i dati di una struttura, instanzia gli oggetti che servono e quindi
chiede agli stessi oggetti di fare certe cose invocando i loro metodi.
Il modo di affrontare il problema e' cambiato completamente: mentre prima
ragionavamo mettendoci nei panni del computer e definendo delle funzioni che
dovevano portare alla soluzione, ora ragioniamo usando i termini del problema e
definiamo degli oggetti che modellano il problema e ognuno dei quali ha
particolari capacita' che permettono di risolvere il problema. Quindi non e'
più il computer che disegna l'evento ma e' l'evento che disegna se
stesso come se ogni oggetto fosse un piccolo computer specializzato.
Incapsulazione,
Ereditarietà, Polimorfismo
Secondo i puristi, quanto detto finora , non basta per fare un linguaggio ad
oggetti: sono necessarie inoltre le tre caratteristiche che adesso vedremo.
Chi usa un oggetto deve conoscere solo i nomi delle proprietà e dei
metodi(ovvero la sua interfaccia) ma
non ha bisogno di conoscere i dettagli dell'implementazione dello stesso che
rimangono incapsulati, nascosti nello stesso: e' questa la cosiddetta incapsulazione dei linguaggi OO. Questa
incapsulazione dovrebbe isolare il codice di un oggetto evitando che il suo
cambiamento possa influenzare il codice di un altro oggetto e si realizza
attraverso particolari attributi che proteggono l'accesso a classi, metodi e
variabili che vogliamo rendere inaccessibili. In particolare incapsulazione
significa proteggere le proprieta' rendendole accessibili solo attraverso
speciali metodi di accesso (getValue)
e di settaggio (setValue).
Se vogliamo modificare una classe non abbiamo bisogno di modificare la classe
originaria(anche se potremmo farlo) come succedeva nella programmazione
funzionale, ma i linguaggi a oggetti ci permettono di definire una nuova classe
che estende o eredita l'altra classe
aggiungendo nuovi metodi e proprieta' ed eventualmente ridefinendo (implementando)quelli della classe
madre: e' questa l'ereditarieta' dei
linguaggi OO.
Sfruttando questo meccanismo i programmi sono in effetti delle gerarchie di
classi che condividono proprieta' e metodi: quando richiamiamo un metodo di un
oggetto proveniente da una classe in questa gerarchia non stiamo richiamando un
metodo ben definito, ma e' compito del linguaggio scoprire all'atto
dell'esecuzione quale metodo andra' richiamato.Questo e' il polimorfismo dei linguaggi OO. Per
questo non abbiamo per i linguaggi ad oggetto la fase di link, ma l'aggancio a
nuove classi avviene in maniera dinamica all'atto dell'esecuzione. Questo
particolare modo di lavorare permette di scrivere programmi che hanno messaggi
"generici" come oggetto.
disegna() che funzionano con diversi tipi di oggetti ed anche con oggetti che
saranno definiti solo nel futuro.
Incapsulazione,ereditarieta' e polimorfismo sono le 3 principali proprieta' che
definiscono i linguaggi OO.
In concreto
Tornando ora al nostro esempio degli eventi, se ora vogliamo aggiornare il
codice, perche' si e' aggiunto un nuovo dato e dobbiamo modificare il
sottoprogramma di disegno degli eventi in modo da utilizzare questo dato, nella
programmazione ad oggetti questo non richiede alcuna modifica al codice
originale. Viene solo aggiunta una nuova classe NuovoEvento aggiungendo le sole proprieta' e metodi modificati. Le
applicazioni precedenti funzionano ancora perfettamente perche' il codice
originario non e' stato cambiato.Inoltre ,se il nuovo codice ha solo ridefinito
vecchi metodi, i vecchi programmi funzioneranno anche con i nuovi eventi senza
cambiare una riga di codice.
Nella programmazione funzionale siamo costretti a modificare il codice
precedente con possibili ripercussioni su tutte le applicazioni che gia' lo
usavano.Intanto dobbiamo aggiungere un nuovo dato in tutte le procedure. Poi
dovremo riscrivere tutte le procedure che usano il nuovo dato.
This,super e
altri oggetti particolari
Nei linguaggi a oggetti le parole this e super hanno un significato speciale.This si riferisce al nome dell'oggetto
del quale in questo momento stiamo eseguendo qualche metodo, super si riferisce invece alla classe
madre di this.Infine in Java tutti gli oggetti sono discendenti da un'unica
classe : la classe Object. Una
sottoclasse viene creata con l'istruzione extends
e può' ereditare da una sola superclasse. Cioe' in Java non abbiamo l'ereditarieta' multipla. La
ridefinizione di un metodo si dice in gergo override mentre l'overload
di un metodo si riferisce alla possibilità di avere più metodi con lo stesso
nome ma con diverso numero e tipo di argomenti. In Java non possiamo invece sovraccaricare(overload in italiano)
gli operatori come +. In Java tutto è
oggetto eccetto gli ottotipi primitivi; percio' per poter operare su di
essi(come oggetti) sono state create 8 classi Wrapper.
Classi Astratte
e Interfacce: 2 classi molto speciali La classe progenitrice di
tutte le altre e' spesso una abstract
class della quale non si possono creare istanze e possiamo usarla solo
estendendola.
Un'interfaccia(interface) e'
anch'essa una classe astratta che contiene solo metodi non implementati. Tali
metodi possono essere implementati da un'altra classe senza bisogno di
estendere la classe ma implementando
la stessa con l'istruzione implements.Una
classe può estendere un'unica classe ma implementare un numero qualsiasi di
interfacce. E' questa la maniera di Java di realizzare l'ereditarietà multipla.
Sia le classi astratte che le interfaccie permettono di descrivere delle
interfaccie che saranno implementate estendendo le stesse. Ad esempio,in Java,
per descrivere come deve essere scritto un oggetto che lavori nel browser si e'
definita la classe astratta Applet.
Chi vuole scrivere un programma che opera in una finestra di un documento Web
estende questa classe implementandone i metodi come paint che indica cosa deve essere disegnato nella finestra.
Packages,strutture
generate dall'ereditarietà e strutture
di dati
Nella programmazione ad oggetti e' facile confondersi se non si capisce bene la
differenza tra classi e oggetti e tra strutture formate da classi e strutture
formate da oggetti. Inoltre abbiamo strutture presenti solo sul programma
scritto e strutture che si creano all'atto dell'esecuzione del programma. Gli oggetti, ad esempio, esistono solo
all'atto dell'esecuzione a differenza della classe che e' presente sia nel
programma scritto che all'atto dell'esecuzione sotto forma di variabili e metodi di classe. Queste
variabili e questi metodi vengono detti in Java statici perche' realizzati attraverso la parola chiave static. Per cui all'atto
dell'esecuzione, per ogni classe usata, avremo le variabili e i metodi statici
sempre presenti piu' un numero variabile(anche 0) di oggetti istanziati. Ogni
oggetto istanziato ha le proprie variabili e i vari oggetti attraverso queste
variabili possono puntare l'uno all'altro creando una struttura di dati:ad esempio una lista. Viceversa le classi,oltre
ad essere organizzate nella loro struttura gerarchica di ereditarieta' (che ha
come effetto all'atto dell'esecuzione che tutte le classi madri di una classe
usata sono caricate) sono raggruppate anche in packages(pacchetti). La divisione in packages non ha niente a che
fare con l'ereditarieta' e viene introdotta per questioni di comodita'. Le
classi di uno stesso package hanno un'accesso
facilitato alle proprie variabili e e ai propri metodi. Questo e' utile per
facilitare la scrittura di classi di
servizio che servono solo a realizzare la funzionalita' presente nelle classi pubbliche del package.Tutte le
classi di un package dividono la stessa cartella che di solito ha lo stesso
nome del package.Queste cartelle possono formare una struttura gerarchica che
non ha nessun particolare significato.Invece il singolo file,in Java,contiene
una sola classe pubblica e un numero qualsiasi di classi di servizio e puo'
quindi essere considerato come un minipackage.
Il livello di accesso di una
classe,variabile o metodo e' definito in Java tenendo conto di queste
strutture.Questo va infatti da private(accesso consentito
nella sola classe) a livello di default (accesso consentito nel pacchetto), a protected accesso consentito alle
classi nel pacchetto e alle classi figlie in altri pacchetti; a public accesso generalizzato.
Persistenza
degli oggetti
La programmazione ad oggetti,mettendo l'accento sugli oggetti, cambia
completamente il modo di considerare l'input/output. Prima si era portati a
considerare le strutture di dati in memoria come separate e diverse dalle
strutture di dati sulle memorie di massa, con istruzioni di I/O che leggendo da
nastro o disco popolano le strutture di dati in memoria.In un linguaggio ad
oggetti questo modo di porre il problema e' (o dovrebbe essere) obsoleto:
abbiamo solo oggetti persistenti (cioe' con una copia su memoria di massa) che
vengono copiati,quando servono, tali e quali e poi eventualmente riscritti se
cambiano di stato. Percio' in un linguaggio ad oggetti invece di parlare di I/O
si parla di persistenza degli
oggetti. Solo alcuni degli oggetti di un programma saranno persistenti, mentre
la maggioranza sara' del tipo transiente
che viene distrutto quando il programma termina l'esecuzione.Java permette di
leggere e scrivere oggetti realizzando la persistenza ma una soluzione
definitiva di questo problema si avra' solo con l'affermarsi dei data base ad oggetti in contrapposizione
ai data base relazionali ora piu' in auge.
In definitiva
...
La classe incapsula certi dati e i metodi per accedervi.Mentre prima chiunque
poteva modificare quei dati, ora dovete farlo passando attraverso la classe e
questo evita un sacco di problemi.
Un programma e' un insieme di oggetti che comunicano tra di loro mandandosi dei
messaggi. Questi messaggi, consistenti nella chiamata di un metodo, chiedono
all'oggetto che riceve il messaggio di fare qualcosa.
Potete pensare a un oggetto come un tipo di dati più complesso che si aggiunge
agli 8 tipi primitivi di dati. A questi dati puoi richiedere di fare certe
operazioni su se stessi, richiamando dei metodi.
Ogni oggetto ha una sua propria memoria che può contenere dati primitivi e
altri oggetti. Questo permette di creare degli oggetti di grande complessità'
partendo da oggetti semplici e impacchettandoli in un nuovo oggetto.
In un programma a oggetti potete inviare dei messaggi generici, a cui ogni
oggetto risponderà a seconda della sua posizione nella gerarchia delle classi.
L'idea di fondo e' di far scrivere ai migliori programmatori degli oggetti che
poi possano essere riusati da tutti per costruire nuove applicazioni.
Java, con le sue librerie specializzate, fornisce migliaia di questi oggetti pronti
per l'uso. Questo ,non solo per facilitare il lavoro dei programmatori, ma
anche per fornire un ambiente di lavoro identico su tutte le piattaforme su cui
Java gira.Imparare a programmare in Java significa innanzitutto conoscere
queste librerie di classi.
Java Development
Kit : JDK
Per programmare in Java occorre procurarsi il JDK della Sun (Java Development
Kit) che e' la distribuzione ufficiale in una delle sue varie versioni. Java
viene fornito come una libreria di classi suddivise in packages e compresse nel
formato zip più una serie di programmi eseguibili. Talvolta questo e' già
disponibile sul computer che usate.Per scoprirlo e sapere quale versione e'
disponibile basta dare il comando(da finestra MSDos su PC):
java -version
Applicazione 1:Il
piu' semplice programma Java
class Ciao
}
Per scrivere programmi Java usate un editore di testi come Wordpad su Pc o vi su Unix.Copiate il programma e salvatelo in un file di nome Ciao.java L'istruzione
javac Ciao.java
compilera' il programma' creando un file: Ciao.class Finalmente l'istruzione
java Ciao
fara' eseguire il programma che scrivera' la frase Ciao a Tutti.
Applet 2:Il
piu' semplice applet
Un applet e' un programma Java che
gira all'interno di un browser.
import java.awt.*;
import java.applet.*;
public class Ciao extends Applet
}
Salvatelo su disco in un file Ciao.java come avete fatto con l'altro programma e poi compilatelo col solito comando:
javac Ciao.java
Questo crea il compilato Ciao.class. Per poterne vedere l'esecuzione dovete inserire il programma Java in una pagina Web. Questo si fa scrivendo un documento HTML con l'istruzione:
<APPLET CODE=Ciao.class Width=300 Height=50>
</APPLET>
che va salvato su disco col nome Ciao.html nella stessa cartella del programma Java. Ora basta leggere il documento col browser per poter vedere il programma in esecuzione. (Se fate queste operazioni su una cartella visibile dal Web e volete accedere all'applet con una URL dovete probabilmente sproteggere i file ciao.htm e ciao.class: su macchine Unix usate il comando
chmod 644 nomefile
Ma in fase di costruzione di un applet e' molto piu' comodo usare uno speciale
programma del jdk chiamato appletviewer:questo
lo si usa col comando
appletviewer Ciao.html
Cercate di familiarizzarvi con questa procedura che sara' usata in tutto il corso.
Privacy |
Articolo informazione
Commentare questo articolo:Non sei registratoDevi essere registrato per commentare ISCRIVITI |
Copiare il codice nella pagina web del tuo sito. |
Copyright InfTub.com 2025