Classi ed Oggetti in JAVA – appunti.

Posted on

Classi ed Oggetti in JAVA – appunti.

JAVA è un linguaggio OOP (Object Oriented Programming).

Un linguaggio OOP implementa tre meccanismi:

L'incapsulamento è il meccanismo che permette ad una classe di nascondere la sua struttura interna e, per utilizzare un componente "incapsulato" di una classe, ho necessità di conoscere a cosa serve il componente e la sua interfaccia. Come è stato costruito il componente posso tranquillamente ignorarlo. Per spiegare meglio il concetto d'incapsulamento facciamo un esempio. Supponiamo essere un'azienda che assembla computers e che si rifornisca da altre aziende per i componenti da assemblare. Se si acquista un Hard Disk dall'azienda X, poichè ci serve una memoria di massa per l'elaboratore che si sta assemblando, l'azienda X non è tenuta a svelare le caratteristiche progettuali dell'Hard Disk; comunica solo come si devono effettuare i collegamenti tra la scheda madre e l'Hard Disk, la capienza dell'Hard Disk, come devono essere trasferiti/prelevati i dati.

Una classe descrive un insieme di oggetti tramite gli attributi, ossia le caratteristiche comuni che posseggono gli oggetti, ed i metodi, il comportamento.

Ad esempio la classe Persona ha come attributi le caratteristiche comuni che posseggono le persone, il nome, il cognome, la data di nascita, il comune e l'indirizzo di residenza…. Nel momento che si istanzia (costruisco) un oggetto della classe, significa che agli attributi associo il nome, cognome, data di nascita relativi ad una determinata persona (un oggetto) della classe, ossia associo, ad esempio. i dati "Mario" al nome, "Rossi" al cognome, 24/11/1980 alla data di nascita….

I metodi, abbiamo detto, definiscono il comportamento della classe. I metodi si suddividono in metodi costruttori che mi permettono di istanziare un oggetto ed i metodi funzione che mi permettono di operare sui dati degli oggetti della classe (ad esempio se volessi conoscere l'età di un oggetto della classe Persona, realizzo un metodo che sottrae la data odierna alla data di nascita).

vediamo quindi come si definisce la classe Persona in Java:

public class Persona
{
    /* Attributi. */
    private String iNome;
    private String iCognome;
    private long iDtNas;

    // Costruttori
    public Persona (String nome, String cognome, long dataNas)
    {
        iNome=nome;
        iCognome=cognome;
        iDtNas = dataNas;
    }
    public Persona ()
    {
        iNome="Mario";
        iCognome="Rossi";
        iDtNas = 1980;
    }
 }

come si può notare, i metodi costruttori dell'esempio di sopra, sono riconoscibili dal fatto che questi metodi hanno lo stesso nome della classe e non hanno altri qualificatori dopo la keyword public. La differenza tra i due è che il primo metodo costruttore ha parametri di input: in fase di costruzione dell'oggetto, l'oggetto avrà i dati passati in input negli attributi, con il sencondo si costruisce un oggetto con i dati di default.

Ma come si istanzia (costruisce) un oggetto? Nel programma in cui voglio costruire l'oggetto (nel Main, in un sottoprogramma,…) si deve usare l'istruzione: NomeClasse NomeOggetto = new NomeClasse (eventuali parametri attuali);

ad esempio:

public class GestisciPersona
{
    public static void main(String[] args)
    {
        Persona pers3 = new Persona("Claudio","Bianchi",1995);
        Persona pers2 = new Persona();
        ………………………………

        ………………………………
    }

}

pers3 sarà un oggetto i cui attributi sono iNome= "Claudio", iCognome="Bianchi", iDtNas=1995;
pers2 sarà un oggetto i cui attributi sono quelli di default ossia iNome= "Mario", iCognome="Rossi", iDtNas=1980;

Come si può notare gli attributi sono stati dichiarati Private. Potevano essere dichiarati anche Public. In cosa consiste la differenza? Gli attributi dichiarati Private realizzano l'incapsulamento, ossia non sono visibili all'esterno della classe. Public non realizza l'incapsulamento: tutto ciò che è dichiarato Public è visibile ed usabile all'esterno della classe.

La domanda che si pone è allora: ma se ho la necessità di modificare un attributo di un oggetto dichiarato Private, come faccio? Bene devo costruire due metodi particolari il metodo SET, che mi permette di modificare un attributo, ed il metodo GET che invece mi permette di visualizzarlo.

Nel nostro esempio:

public class Persona
{
    /* Attributi. */
    private String iNome;
 
    ………………………………….
    ………………………………….
    …………………………………. 

  /* Set method per modificare l'attributo Private iNome */

   public void setNome (String pNome)
    {iNome=pNome;}

   /* Get Method che restituisce l'attributo iNome */

   public String getNome ()
    {return iNome;}

    ………………………………….
    ………………………………….
    …………………………………. 

}

Abbiamo detto che ci sono dei metodi (funzioni) che manipolano i dati degli oggetti. Ad esempio vogliamo costruire un metodo che ci calcoli l'età di una persona:

public class Persona
{
    /* Attributi. */
    private String iNome;
    private String iCognome;
    private long iDtNas;

    ………………………………….
    ………………………………….
    …………………………………. 


   public long CalcolaEta ( long DtAttuale)
   {return (dtAttuale – iDtNas);}


    ………………………………….
    ………………………………….
    …………………………………. 
}

il metodo CalcolaEta deve essere invocato sugli oggetti, ad esempio:

public class GestisciPersona
{
    public static void main(String[] args)
    {
        Persona pers3 = new Persona("Claudio","Bianchi",1995);
        Persona pers2 = new Persona();
        System.out.println(pers3.CalcolaEta(2017)); /* visualizzerà 22 */
        System.out.println(pers2.CalcolaEta(2017)); /* visualizzarà 37 */
        ………………………………

        ………………………………
    }

}

L'ereditarietà è un meccanismo che consente di creare nuovi oggetti partendo da oggetti già esistenti. Ovviamente questi oggetti devono avere attinenza tra di loro, Per il nostro esempio, supponiamo di voler costruire la classe Impiegato. Un Impiegato altri non è che una Persona che lavora in qualche ufficio. Quindi se devo creare la classe Impiegato, posso utilizzare tutti gli attributi e metodi della classe Persona aggiungendo solo quegli attributi e metodi che sono propri della classe Impiegato. La classe di partenza (nel nostro esempio Persona) prende il nome di Superclasse la classe che eredita (Impiegato) prende il nome di Sottoclasse.

Per costruire una classe partendo da una già esistente si utilizza il comando extends:

public class Impiegato extends Persona
{
    // ATTRIBUTO DI IMPIEGATO;
    private String iDitta;

    //COSTRUTTORE;
    public Impiegato (String nome, String cognome, long dataNas, String ditta)
    {
        super (nome, cognome, dataNas);
        iDitta = ditta;
    }
        ………………………………

        ………………………………
 }

anche se nella classe Impiegato compare il solo attributo iDitta (nome della ditta ove lavora l'impiegato), in realtà la classe ha ereditato non solo gli attributi di Persona, ma anche tutti i metodi (quindi anche CalcolaEta). Si noti, infatti, come il costruttore della classe, abbia come parametri, i parametri di Persona con l'aggiunta del parametro per avvalorare la ditta ove lavora l'impiegato. Per far "funzionare" il costruttore della classe Persona all'interno della classe Impiegato si utilizza la keyword super con i parametri relativi agli attributi di Persona.

Il termine polimorfismo indica la capacità di qualcosa di assumere diverse forme. Nel caso delle classi indica la capacità di un metodo di comportarsi in modi differenti a secondo del modo in cui il metodo è richiamato. I metodi polimorfici possono essere realizzati in due modi differenti:


POLIMORFISMO OTTENUTO TRAMITE L'OVERLOAD DEI METODI
POLIMORFISMO OTTENUTO TRAMITE L'OVERRIDE DEI METODI

L'overloading si ottiene creando nella stessa classe, due o più metodi con lo stesso nome ma che hanno parametri di input differenti (come tipo e/o come numero e/o l'ordine di presentazione) e/o tipologie diverse. In realtà l'overloading l'abbiamo già incontrato quando abbiamo creato i metodi costruttori: il metodo costruttore che presupponeva l'uso di parametri ed il metodo costruttore di default. Entrambi avevano lo stesso nome (quello della classe), ma quando istanziavamo un oggetto, se si istanziava passando dei parametri, veniva richiamato il metodo costruttore creato con i parametri formali, se non passavamo parametri, veniva richamato il metodo costruttore di default.

Vediamo un altro esempio.

public class Calcolatrice
{
public int sum(int a,int b)
    
{return (a+b);}

public int sum(int a,int b,int c)
    
{return (a+b+c);}

}
public static void main(String args[])
{
       int A, B;
      
Calcolatrice cal = new Calcolatrice();
       A = cal.sum(20,30,60); /* A contiene 110 */
       B =
cal.sum(20,20);      /* B contiene 40 */

} 

nell'esempio sopra riportato, lo "stesso" metodo sum somma o due o tre numeri indifferentemente.

L'overriding si ottiene in gerarchie di classi realizzate grazie l'ereditarietà. In questo caso i metodi, che hanno lo stesso nome , si trovano nelle varie classi, e funzionano diversamente in base a quale classe è stato istanziato l'oggetto ove vengono fatte eseguire. 

Ritorniamo alla superclasse Persona e alla sottoclasse Impiegato: nelle due classi creiamo lo stesso metodo Visualizza, che restituisce in output gli attributi degli oggetti.

public class Persona
{

    ………………………………….
    ………………………………….
    …………………………………. 

   public String Visualizza ()
   {
       return ( "nome: "+ iNome + " cognome: " + iCognome + " Data di nascita: " + iDtNas);
   } 

}

public class Impiegato extends Persona
{

    ………………………………….
    ………………………………….
    …………………………………. 

   public String Visualizza ()
   {
       return ( "nome: "+ iNome + " cognome: " + iCognome + " data di nascita: " + iDtNas + " ditta: "+ iDitta);
   } 

}

public class GestisciPersona
{
    public static void main(String[] args)
    {
        Persona pers = new Persona("Claudio","Bianchi",1995);
        Impiegato imp= new Impiegato("Guido","Rossi",1980,"La Mia Ditta S.p.A.");


        System.out.println(pers.Visualizza()); /* visualizzerà: nome: Claudio cognome: Bianchi data di nascita:                                                                                                                                                                                 1995 */
        System.out.println(imp.Visualizza()); /* visualizzarà:
nome: Guido cognome: Rossi data di nascita:                                                                                                                                               1980 ditta: La Mia Ditta S.p.A.*/

        ………………………………
        ………………………………
    }

}

Massimo Stefanizzi
Author