MokaByte Numero 01 - Ottobre 1996
La Programmazione 
ad oggetti
 
di
Giovanni Puliti 
Seconda parte

 


 
 

Prosegue il corso sulla programmazione ad oggetti inizato il nel numero scorso. In questo numero inizamo ad affrontare in concreto i concetti legati all programmzione OO. 

Innanzi tutto occorre chiarire cosa sia un oggetto, e perché sia stato tanto importante creare un nuovo modo di programmare basato su questa filosofia . Come prima cosa diciamo che in realtà sarebbe più esatto parlare di classi e non tanto di oggetti: la differenza è che una classe è il tipo, l’entità l’idea, mentre un oggetto è la sua istanziazione. Si pensi al tipo int ed a una variabile di tipo intero. Una classe é l’elemento basilare atteaverso il quale si può progettare un sistema costruire un progetto più o meno complicato.

Se ci soffermiamo a considerare un qualsiasi sistema più o meno complesso, lo si può pensare come costituito da parti ognuna delle quali ha delle caratterisitiche ben precise ed è in grado di svolgere determinati compiti. Si pensi all’oggetto automobile, o meglio alla classe automobile: essa ha delle proprietà, come il colore, il numero delle porte, il peso e così via.... Ma una automobile è in grado anche di svolgere delle operazioni, quali ad esempio spostarsi, accellerare, o frenare. Non entreremo adesso nel merito del fatto che in realtà queste operazioni sono compiute da un uomo che comanda l’auto, ma vedremo in seguito come specificare tale situazione attraverso la OO. Il grosso vantaggio sta nel fatto che per l’utilizzatore, non è importante sapere come un oggetto esegue certe operazioni, ma solo che è disponibile un certo servizio. Non e’ necessario conoscere i dettagli costruttivi di una autovettura: si preme il pedale del freno e la macchina rallenta. Nella OO si è riprodotto tutto questo: una classe rappresenta una scatola nera di cui non è necessario conoscere i dettagli implementativi, ma solo le sue funzionalità e proprietà disponibili. E’ chiaro che è necessario avere un minimo di conoscenza delle caratteristiche operatrive della classe e quali siano le istruzioni da compiere per poterla gestire, ma il tutto si limita, almeno in teoria, alla conoscenza delle specifiche operative. 

Si definisce l’insieme delle specifiche di chiamta dei metodi e dei nomi delle variabili accessibili dall’esterno, interfaccia della classe. Attraverso l’interfaccia è possibile controllare completamente una classe; essa ci mette a disposizione tutte e sole le proprietà ed i metodi operativi, mentre non ci dà nessuna possibilità di interferenza sulle variabili e sulle procedure interne: esse servono alla classe per svolgere le operazioni che le sono richieste dall’esterno. Questo aspetto viene definto a volte come information hiding, ed è uno degli obiettivi fondamentali nello sviluppo di progetti di grosse dimensioni: il nascondere i dettagli implementativi permette di mantenre la chiarezza, l’eleganza del codice, e semplifica enormemente la fase di design e sviluppo. Nel caso della programmazione ad oggetti si parla di incapsulamento. Esso oltre a mantenere pulito il progetto, se ben implemetato, permette di ridurre i tempi di sviluppo. 

Si pensi ad esempio ad una certa classe di interfacciamento col file sistem del sistema operativo, la classe file: essa ha implementate tutte le routine tipiche quali apri file, chiudi, leggi, scrivi e così via. Quando utilizzata nell’ambito di un progetto più completo tale classe fornisce i suoi servizi senza che ci si debba preoccupare di come sia stata implementa la routine che legge un byte. Inoltre cosa ancora più utile della OO, se un domani la classe file non dovesse essere più usabile per un qualche nuovo dettaglio sopravvenuto nel formato dei file, basterà sostituirla mantenendo l’interfaccia inalterata, ed il progetto continuerà a funzionare perfettamente. Al limite basterà riscrivere solo il codice del metodo che non è più utile. Questo aspetto da luogo ad uno dei sogni di tutti gli informatici dai tempi delle macchine di Von Neumann: la riusabilità del codice. Vedremo che in realtà le cose non sono così rosee, ma in teoria la OO permette di risprmiare un sacco di energie. 

Prima di vedere come può essere strutturata una classe al suo interno vediamo di affrontare l’altro punto fondamentale della OO. 

L’ereditrarietà. Con tale costrutto è possibile derivare da una classe già esistente crearne una nuova variando tutte o in parte le vecchie funzionalità o aggiungendone delle nuove. Potremmo ad esempio partendo dalla classe file, definire una classe fileordinato. Essa avrà tutte le funzioalità della classe base, le eredita appunto, ed in più avrà ad esempio, un metodo aggiuntivo che le permette di ordinare le parole presenti in un file di testo. Allo stesso modo in una classe derivata vi è la possibilità di aggiungere variabili. L’ereditarietà ci permette quindi di creare delle gerarchie di classi in cui ogni figlio eredita dal padre tutte le sue caratteristche con la possibilità di variarne alcune o di averne altre in aggiunta. Nella gerachia di oggetti che si viene a creare si dice che ogni legame fra classe padre e figlio da luogo ad una realzione di tipo generalizzazione-specializzazione, proprio perché scendendo verso il basso si trovano classi sempre più specializzate e verso l’altro sempre più generiche. 

Java implementa l’ereditarietà in modo molto pulto eliminando alcune dei costrutti pericolosi del C++ che col tempo per vaire necessità si erano venuti creando.

Adesso che abbiamo parlato si ereditarietà e di come si possa usare una classe, vediamo come è strutturata una classe. Non entreremo nei dettagli sintattici per i quali rimandiamo ad uno qualsiasi dei manuali reperibili.

A grandi linee abbiamo gia detto che una classe ha funzioni e variabili ad uso esterno e ad uso interno. Per poter implementare tale meccanismo di visibilità si utilizzano i cosidetti specificatori di accesso o di scope. In particolare in Java esistono i seguenti dichiaratori: public, protected e private, più le possibili combinazioni.

Si può così dire se una funzione particolare è visibile dall’esterno oppure no, e quindi invocabile o no. Lo stesso discorso vale per le variabili. Per poter capire meglio questo punto e non creare confusione nel lettore, ho pensato di parlare in particolare di come è organizzato il linguaggio Java. Non mi sembrava infatti opportuno continuare a esporre la teoria in modo troppo generico per mantenere un certo rigore teorico. In questa sezione adottiamo un’altra visione delle cose. Si punta l’attenzione sulla facoltà degli elementi di fungere da contenitori. In java in particolare esiste un altro modo per incapsulare dati e codice in modo sicuro: attraverso l’uso dei package. Un package è un contenitore di classi e di altri package, mentre una classe può contenere dati e funzioni. In realtà questa visione non è completa, am affronteremo in futuro maggiori approfondimenti.

Quindi secondo una tecnica che ricorda il gioco delle scatole cinesi, ci troviamo di fronte ad una struttura a contenitori concentrici. Si ricordi che in tale gerachia la classe è l’elemento di base e che non è possibile trovare codice separato da essa. Per un maggior chiarimento su cosa sia un pakage nel linguaggio Java si veda l’articolo presente in questo numero di F.Giudici Java e C++.

Vediamo cosa è possibile fare quindi nel nostro caso (nostro di Java!): ovviamente all’interno di una classe ogni entità è visibile da ogni punto della classe stessa. Per quanto riguarda la visibilità all’esterno della classe e del package le cose possono essere diversificate. In particolare si può specificare le modalità di accesso considerando il seguente schema: Sottoclassi all’interno dello stesso package Classi nello stesso package ma che non sono sottoclassi Sottoclassi in package diversi Classi in sottoclassi diverse ma che non sono sottoclassi

Per non dilungarmi troppo in schemi a volte di non facile comprensione ecco qui di seguito alcuni semplici esempi. Ogni elemento dichiarato public è visibile da ogni posizione, mentre tutto ciò che è dichiarato private non può essere visto al di fuori della classe. Se un elemento non ha spcificatori di accesso allora per default sarà visibile solo da sottoclassi e alle altre classi nello stesso package. Se vogliamo rendere un elemento visibile al di fuori del package ma solo a sottoclassi della classe in questione dobbiamo usare protected. Se usiamo private protected allora l’elemento in questione sarà visibile da sottoclassi indipendentemente dal package in cui si trovano.

Per questa volta ci fermiamo qui; nel prossimo numero approfondiremo i concetti visti, con qualche piccolo esempio. 

Si parlerà anche dell’altro tipo fondamentale di relazione in OO, la relazione tutto parti. In particolare vedremo di enunciare alcune tecniche empiriche per capire meglio come organizzare le gerchie fra classi. Sarà questo il punto fondamentale della serie di articoli riguardanti la OO. Come al solito rivolgo l’invito a coloro che avessero da propormi commenti suggerimenti critiche deplorazioni ed ingurie virtuali, a scrivermi tramite la redazione.

 

MokaByte rivista web su Java

MokaByte ricerca nuovi collaboratori
Chi volesse mettersi in contatto con noi può farlo scrivendo a mokainfo@mokabyte.it