Luigi Arlotta
a- a+

Classi e Oggetti

In questo capitolo impareremo a definire le classi e quindi ad utilizzare gli oggetti. Abbiamo già detto più volte nei capitoli precedenti che un oggetto è un insieme di dati e funzioni che ne definiscono lo stato ed il comportamento. In Java le classi sono dei modelli per gli oggetti, ovvero sono delle strutture dati utilizzate per definire le caratteristiche e le funzionalità di un determinato tipo di oggetto. Una classe, una volta definita, viene instanziata creando un oggetto. E' importante non far confusione tra la definizione di una classe e l'instanzizione di un oggetto. Definire una classe consiste nell'elencare una serie di proprietà e funzioni, instanziare un oggetto invece vuol dire creare una variabile che presenta le caratteristiche della classe da cui è stata generata.

Potremmo affermare che una classe è la definizione di un tipo di dato strutturato definito per rappresentare un'entità complessa quale può essere ad esempio un conto bancario, un prodotto commerciale, una persona. Affrontiamo dunque lo studio delle classi Java supponendo di aver bisogno di progettare una classe che rappresenti un impiegato di una società.
Innanzitutto dobbiamo chiederci quali informazioni sono di nostro interesse, per la definizione della classe che chiameremo Impiegato. Trattandosi di un progetto a fini didattici, semplificheremo il più possibile la definizione della classe Impiegato, partendo proprio dalle proprietà di nostro interesse. Supponiamo che un impiegato sia caratterizzato dalle informazioni relative al nome, cognome, anno di nascita, stipendio e posizione in azienda. Cominciamo a tradurre quanto detto fino ad ora secondo la sintassi Java.

public class Impiegato {
private String nome;


private String cognome;
private int annoNascita;
private int stipendio;
private String posizione;
final int stipendioMax;
final int stipendioMin; }


Procediamo con la spiegazione di quanto scritto. La prima riga contiene la dichiarazione della classe. In essa compare la parola chiave class che indica al compilatore Java l'operazione che stiamo eseguendo. La classe Impiegato è definita public, cioè pubblica. Questo vuol dire che potrà essere utilizzata o inclusa in altre classi o più in generale in altri progetti, senza alcuna restrizione. Le parentesi graffe ({, }) racchiudono il codice che definisce la classe. All'interno compare la dichiarazione delle proprietà che abbiamo considerato di nostro interesse per la definizione di un oggetto di tipo Impiegato. Tali proprietà sono il nome, cognome e posizione in azienda rappresentate da tre variabili di tipo String chiamate rispettivamente nome, cognome e posizione. A queste si aggiungono le informazioni riguardanti anno di nascita e stipendio, rappresentate da altre due variabili di tipo int chiamate rispettivamente annoNascita e stipendio. Infine compare la dichiarazione di due costanti di tipo intero che rappresentano rispettivamente lo stipendio minimo e massimo che può ricevere un impiegato: stipendioMin e stipendioMax. Osservate che nessuna di queste variabile è stata inizializzata in questa fase di definizione della classe.
Ogni dichiarazione di variabile contenuta nella classe è composta [...].
[Pending: dichiarazioni variabili e parola chiave private]

Una volta definite le proprietà di una classe dobbiamo aggiungere una serie di funzioni, che in java vengono più propriamente detti metodi che operando sulle proprietà descrivendo il comportamento e le operazioni che sarà possibile effettuare sugli oggetti che verranno generati dalla classe. I metodi che siamo interessati a definire per la classe Impiegato sono riportati in tab.8.1 dove è descritta anche la funzione alla quale dovranno assolvere.



motraNome() visualizzerà nome e cognome dell'impiegato
calcolaStipendio() restituirà un valore intero pari allo stipendio
calcolaEta(int anno) restituirà un valore intero pari l'età dell'impiegato in particolare anno
variaStipendio(int variazione) varia lo stipendio
aumentaStipendio(int aumento) incrementerà lo stipendio di una quantità pari a aumento
riduciStipendio(int riduzione) ridurrà lo stipendio di una quantità pari a riduzione
Tab.8.1: Metodi della classe Impiegato



Una volta completata la definizione della classe Impiegato sarà possibile instanziare diversi oggetti di tipo Impiegato, ognuno caratterizzato da un proprio stato. Col termine stato indichiamo l'insieme dei valori assegnati alle proprietà di ogni oggetto. Ad esempio instanzieremo un oggetto che rappresenti l'impiegato Mario Rossi, nato nel 1964, ... un secondo oggetto che rappresenta l'impiegato Luigi Verdi, nato nel 1970, ... e così via. Ad ognuno di questi oggetti, identificato da un nome esattamente come avviene per le variabili, sarà possibile applicare i metodi appena elencati, ed a seconda dell'oggetto a cui verranno applicati questi metodi otterremo risultati diversi, appunto, in base allo stato dell'oggetto in questione. Dovendo definire questa classe a fini didattici abbiamo inserito tre metodi che modificano la proprietà stipendio, mentre probabilmente ne sarebbe bastato uno. Questa scelta è stata fatta per evidenziare alcune proprietà dei metodi che verranno evidenziate nel corso di questo capitolo.

Cominciamo a scrivere il codice per la definizione dei metodi. Per definire il metodo mostraNome() scriveremo:


public void mostraNome()
{
System.out.println(nome + " " + cognome); }


Il metodo è costituito da un'intestazione e da un corpo racchiuso tra le parentesi graffe. Soffermiamoci ad osservare l'intestazione:

public void mostraNome()

in essa compare la visibilità del metodo pubblic che definisce il metodo come pubblico, cioè accessibile (visibile) dall'esterno della classe. In poche parole questo vuol dire che una volta instanziato l'oggetto, il metodo potrà essere liberamente richiamato per operare sull'oggetto stesso. Ai metodi pubblici si contrappongono quelli definiti utilizzando la parola chiave private, i quali non possono essere richiamati dall'esterno, ma possono essere utilizzati solo all'interno della classe. Parleremo dei metodi privati tra poco. La seconda parola chiave, void, indica il tipo di dato restituito dal metodo al termine dell'esecuzione. Generalmente un metodo esegue un'elaborazione su dati immessi dall'esterno e/o sulle proprietà dell'oggetto su cui viene richiamato. L'elaborazione porta ad un risultato che viene restituito come output. Questo valore può essere di tipo intero (int), decimale (float o double), stringa (String), o di un qualsiasi altro tipo. In fase di progettazione di un metodo è necessario dichiarare il tipo di valore che verrà restituito al termine dell'esecuzione delle istruzioni contenute nel metodo. Se il metodo non restituisce nessun valore si usa la parola chiave void. Questo è il nostro caso, infatti il metodo mostraNome() visualizza nome e cognome dell'oggetto Impiegato su cui è stato richiamato senza restituire alcun valore. Infine, nella riga d'interstazione, compare il nome del metodo, seguito da una coppia di parentesi tonde in cui possono essere opzionalmente indicati i parametri richiesti in input dal metodo. Nel caso di mostraNome() nessun parametro di input è richiesto.
Il corpo della funzione è costituito semplicemente dall'istruzione:

System.out.println(nome + " " + cognome);

Istruzione già incontrata in precedenza, il cui scopo è visualizzare una stringa contenente il valore delle proprietà nome e cognome dell'oggetto di tipo Impiegato su cui è stato richiamato il metodo separate da uno spazio.

Passiamo a definire il secondo metodo della classe Impiegato, calcolaStipendio().

public int calcolaStipendio ()
{
return stipendio; }

 

Anche in questo caso vogliamo analizzare l'intestazione del metodo. Rispetto al metodo precedente in questo caso abbiamo dichiarato che il metodo restituisce un'informazione (output) sotto forma di numero intero. Questa dichiarazione viene rispettata nel corpo del metodo utilizzando la parola chiave return. return infatti, seguito da una variabile o da una costante, assolve proprio a questo compito. In questo caso dunque viene restituito, come output, il valore contenuto nella proprietà stipendio. E' importante assicurarsi che il tipo della variabile restituita coincida con il tipo del metodo dichiarato nell'intestazione. In questo caso il tutto risulta corretto in quanto abbiamo dichiarato che il metodo restituisce un valore di tipo intero (int), che è effettivamente anche il tipo della variabile stipendio.

Procediamo nella definizione del metodo calcolaEta().

public int calcolaEta (int annoCorrente)
{
int eta = annoCorrente - annoNascita;


if ((eta>=16) && (eta<=90))
return eta; else
return 0;

}

Nell'intestazione di questo metodo compare un'ulteriore differenza rispetto ai due metodi appena descritti. In questo caso abbiamo un metodo pubblico, che restituisce un valore di tipo intero e che richiede un parametro di input, anch'esso di tipo intero. Questo è quanto si deduce osservando l'intestazione del metodo. In particolare il tipo del parametro di input richiesto è indicato tra le parentesi che seguono il nome del metodo. Oltre al tipo viene indicato il nome che verrà attribuito al valore intero passato in input per farvi riferimento all'interno del corpo della funzione. Nel corpo della funzione viene dichiarata ed inizializzata una nuova variabile di tipo intero, chiamata eta. L'inizializzazione di questa variabile dipende dalla proprietà annoNascita dell'oggetto su cui viene richiamato il metodo e dal parametro annoCorrente passato come input. Per come è formulata l'istruzione di inizializzazione della variabile eta è ovvio che essa contiene l'età dell'impiegato. Segue un'istruzione if... then... else... il cui scopo è controllare che il parametro di input sia valido. Il controllo cosiste nel verificare che la variabile eta, a seguito dell'inizializzazione abbia assunto un valore compreso tra 16 e 90. L'età di 16 anni è la minima età lavorativa imposta per legge, per quanto riguarda il limite superiore si è invece supposto di non aver impiegati ultranovantenni. Se il controllo ha esito positivo viene restituito un numero intero rappresentate l'età dell'impiegato in questione, altrimenti viene segnalato l'errore tramite la restituzione di un'età pari a 0.

Definiamo il metodo variaStipendio().

private void variaStipendio (int variazione)
{
if (stipendio + variazione > stipendioMin)
stipendio = stipendio + variazione; else
stipendio = stipendioMin;

if (stipendio > stipendioMax)
stipendio = stipendioMax;

}

 

Dall'intestazione del metodo risulta che variaStipendio() è un metodo privato (definito tale dalla parola chiave private). Questa caratteristica fa si che una volta instanziato un oggetto di tipo Impiegato, non sarà possibile richiamare direttamente su di esso il metodo variaStipendio(). Un metodo privato può essere richiamato solo da altri metodi definiti internamente alla classe di appartenenza. Nel nostro caso il variaStipendio() verrà utilizzato dai metodi aumentaStipendio() e riduciStipendio(), per modificare la proprietà stipendio. Il metodo riceve in input un parametro intero, a cui viene attribuito il nome variazione, che può essere sia positivo che negativo. Nel corpo del metodo viene effettuato un primo controllo tramite un'istruzione if... then... else... sul parametro variazione al fine di verificare che una eventuale eccessiva riduzione dello stipendio non lo faccia risultare inferiore al valore stipendioMin che indica lo stipendio minimo percepito da un impiegato. Un secondo controllo invece assicura che lo stipendio, una volta registrata la variazione non superi la soglia massima definita tramite la costante stipendioMax.

Analizziamo i metodi aumentaStipendio() e riduciStipendio(). Osserviamo come questi facciano uso del metodo privato variaStipendio() per assolvere al proprio compito, quindi senza doversi preoccupare di eseguire alcun tipo di controllo sulle eventuali eccessive variazioni della proprietà stipendio.

public void aumentaStipendio (int incremento)
{

variaStipendio (incremento); }


Il metodo aumentaStipendio() è un metodo pubblico, non restituisce alcun valore ma ne richiede uno in input di tipo intero (int) cui viene dato il nome incremento. Il metodo opera sulla proprietà stipendio dell'oggetto richiamando variaStipendio().

Definiamo il metodo riduciStipendio().

 

public void riduciStipendio (int riduzione)
{
variaStipendio (riduzione*(-1)); }

 

Il metodo riduciStipendio() è un metodo pubblico, non restituisce alcun valore ma ne richiede uno in input di tipo intero (int) cui viene dato il nome riduzione. Il metodo opera sulla proprietà stipendio dell'oggetto su cui viene richiamato utilizzando il metodo variaStipendio().

Fino ad ora abbiamo definito proprietà e metodi della classe Impiegato. Siamo a buon punto, ma non abbiamo ancora concluso il nostro lavoro, infatti, se ben ricordate, al momento della dichiarazione delle proprietà, ci siamo limitati ad elencarle, senza preoccuparci di come queste verranno inizializzate. L'inizializzazione di un oggetto, al momento della sua creazione, avviene attraverso un metodo particolare detto costruttore. Il costruttore è un metodo che viene richiamato automaticamente ogni volta che viene creato un nuovo oggetto al fine di inizializzarlo. Il costruttore per essere distinto dagli altri metodi deve avere lo stesso nome della classe, quindi nel nostro caso, si deve chiamare Impiegato(). Definiamo il costruttore della classe Impiegato.

public Impiegato (String nome, String cognome, int annoNascita, String posizione)
{
stipendioMin = 750;


stipendioMax = 2000;
this.nome = nome;
this.cognome = cognome;
this.annoNascita = annoNascita;
stipendio = stipendioMin;
this.posizione = posizione; }

Analizzando l'intestazione del costruttore della classe Impiegato notiamo subito che si tratta di un metodo pubblico (public), che non è specificato alcun tipo di dato restituito. Tutti i costruttori devono avere queste due caratteristiche. Non è possibile definire costruttori di tipo private o che restituiscano un qualche tipo di valore in output. Il costruttore della classe Impiegato richiede in input quattro parametri: nome, cognome, anno di nascita e posizione del nuovo oggetto di tipo Impiegato che verrà generato. Osserviamo che ai parametri passati in input viene dato lo stesso nome delle proprietà della classe. Questa procedura, che altrimenti potrebbe generare confusione, viene risolta utilizzando la parola chiave this all'interno del corpo del costruttore. L'uso di this è un modo per far riferimento ad una proprietà dell'oggetto che stiamo generando. In questo modo, pur avendo entrambe lo stesso nome, non si farà confusione tra le variabili passate al costruttore e le corrispondenti proprietà dell'oggetto. Per evitare l'uso della parola chiave this avremmo potuto scrivere:

public void Impiegato (String n, String c, int a, String p)
{
stipendioMin = 750;


stipendioMax = 2000;
nome = n;
cognome = c;
annoNascita = a;
stipendio = stipendioMin;
posizione = p; }


All'inizio questo potrebbe sembrarvi il modo più semplice di procedere, tuttavia una volta appreso il funzionamento della parola chiave this, vi verrà più naturale scrivere i costruttori, ed in generale ogni altro metodo, come descritto nel primo esempio.

All'interno del corpo del costruttore possiamo richiedere l'esecuzione di qualsiasi tipo di operazione, tuttavia è buona norma limitarsi all'inizializzazione delle proprietà dell'oggetto.

A questo punto abbiamo decisamente completato la definizione della classe Impiegato! Per comodità vi riporto di seguito l'intero codice. Ho ordinato il codice secondo le convenzioni in uso tra i programmatori Java, ossia prima il costruttore, poi i metodi pubblici e privati, quindi le proprietà pubbliche, quelle private ed infine le costanti.


public class Impiegato {


public Impiegato (String nome, String cognome, int annoNascita, String posizione)
{
stipendioMin = 750;


stipendioMax = 2000;
this.nome = nome;
this.cognome = cognome;
this.annoNascita = annoNascita;
stipendio = stipendioMin;
this.posizione = posizione; }

public void mostraNome()
{
System.out.println(nome + " " + cognome); }



public int calcolaStipendio ()
{
return stipendio; }



public int calcolaEta (int annoCorrente)
{
int eta = annoCorrente - annoNascita;


if ((eta>=16) && (eta<=90))
return eta; else
return 0; }



public void aumentaStipendio (int incremento)
{
variaStipendio (incremento); }



public void riduciStipendio (int riduzione)
{
variaStipendio (riduzione*(-1)); }



private void variaStipendio (int variazione)
{
if (stipendio + variazione > stipendioMin)
stipendio = stipendio + variazione; else
stipendio = stipendioMin;

if (stipendio > stipendioMax)
stipendio = stipendioMax;

}

private String nome;
private String cognome;
private int annoNascita;
private int stipendio;
private String posizione;
final int stipendioMax;
final int stipendioMin; }

 



Ti potrebbe interessare anche

commenta la notizia

Ci sono 3 commenti