Ripasso: Classi e Oggetti

Le classi in Java possono avere due ruoli:
  1. Classi come prototipi (template) di oggetti;
  2. Classi come contenitori di variabili e metodi statici.
Questi due ruoli possono essere presenti contemporaneamente in una classe.


Nel primo ruolo, una classe descrive le caratteristiche comuni di una collezione di oggetti (si pensi ad esempio alla classe BankAccount). La dichiarazione di classe introduce un nuovo tipo di dato (la classe stessa), i cui elementi saranno i suoi oggetti.
Nella classe vengono dichiarati:
  • le variabili di istanza, che costituiscono lo stato degli oggetti;
  • i metodi di istanza, che realizzano le funzionalità degli oggetti;
  • i costruttori, che determinano le modalità di creazione degli oggetti.
Quando un oggetto viene creato con new, gli viene associata una copia di ogni variabile di istanza.


Per accedere ad una variabile di istanza di un oggetto, si usa la sintassi
<oggetto>.<nomeVariabile>
e analogamente per invocare un metodo, si scrive
<oggetto>.<nomeMetodo>(<listaParametri>)
Ad esempio,
 
 
BankAccount conto1 = new BankAccount(1000);
conto1.withdraw(500);
// crea un oggetto
// chiamata metodo





Dichiarazioni di classi

Lo schema generale di dichiarazione di una classe in Java è il seguente:
 
 
<modif> class <nome-classe> {
<costruttori>
<variabili statiche>
<metodi statici>
<variabili d'istanza>
<metodi d'istanza>
}

Variabili e metodi (di istanza o statici) sono chiamati anche membri della classe. L'ordine delle dichiarazioni all'interno del corpo di una classe non è importante.
 

 




Creazione di oggetti

Il processo di creazione di un oggetto consiste in
  • Allocare lo spazio di memoria necessario a contenere l'oggetto.
  • Inizializzare le variabili di istanza dell'oggetto.
La quantità di memoria necessaria per contenere un oggetto è determinata univocamente dalla dichiarazione della classe (più precisamente, dal numero e dal tipo delle variabili di istanza).
[Naturalmente lo stesso vale anche per gli array].

Lo spazio necessario viene allocato in una zona di memoria chiamato heap.

Come sappiamo, un oggetto viene creato con la primitiva new:

new <nomeClasse>(<parametri>)
Ad esempio:
new BankAccount(1000) // crea un nuovo conto con saldo 1000
La primitiva new fa concettualmente tre cose:
  • Crea l'oggetto allocando la memoria necessaria;
  • Invoca sull'oggetto un costruttore della classe <nomeClasse>, passandogli i <parametri>;
  • restituisce un puntatore all'oggetto creato.
Vediamo più in dettaglio cosa sono i costruttori.

 




Costruttori 

I costruttori si dichiarano all'interno di una classe essenzialmente come i metodi, ma rispettando le seguenti regole:
  • il nome del costruttore deve coincidere con quello della classe; 
  • un costruttore non può avere un tipo (nemmeno void) 

  • (concettualmente, il costruttore restituisce sempre l'oggetto appena creato);
  • non può avere static come modificatore. 
Come per i metodi, anche ai costruttori si applica l'overloading: una classe può avere più costruttori purché abbiano firma diversa (cioè i parametri formali devono differire nel tipo e/o nel numero).
 
 
Esempio: costruttori della classe BankAccorunt
public BankAccount (int initialCapacity)
public BankAccount ()

Se in una classe è definito almeno un costruttore, l'operatore new  chiama sull'oggetto appena creato il costruttore determinato dalla lista dei parametri attuali (se non esiste, si verifica un errore).




Dichiarazione di metodo

Sintassi:
<modif> <tipo> <nome> (<par formali>){
    <corpo>
}
Esempio (dalla Classe java.lang.Math)
    public static double sqrt (double a){
        double b;
        <istruzioni che calcolano la radice quadrata di a in b>
        return b;
    }
dove:
  • <modif>: Modificatori. Descrivono proprietà del metodo come visibilità (da chi può essere usato), modificabilità, appartenenza ad una classe o alle istanze.
  • <tipo>: Il tipo del metodo. E' il tipo del dato restituito dal metodo, oppure void.
  • <nome>: Il nome del metodo. E' un identificatore qualunque, che individua il metodo all'interno della classe.
  • <parametri formali>: I parametri formali. Una lista (anche vuota) di coppie <tipo> <parametro> separate da virgole, dove <tipo> è un tipo di dato e <parametro> è una variabile (identificatore)
  • <corpo>: Il corpo del metodo. Un blocco che contiene istruzioni fra cui una o più istruzioni return (secondo le regole che vedremo dopo).



Firma di un metodo e overloading

Java consente di chiamare più metodi con lo stesso nome (overloading),  purché abbiano una diversa firma (signature).
La firma di un metodo
<modif> <tipo> <nome> (<tipo1> <par1>, ... ,<tipon> <parn>){
...
}


è la sequenza (<nome>, <tipo1>, ..., <tipon>).
Attenzione: la firma non comprende il tipo del metodo, né i nomi dei parametri formali.


Esempio (dalla classe java.lang.Math). I metodi min restituiscono il
minore tra due numeri:

  • public static int min (int a, int b)
  • public static double min (double a, double b)
  • Si noti che
    • hanno come firma(min, int, int) e (min, double, double)
    • è naturale chiamarli con lo stesso nome
    • anche se ogni int è un double, non possiamo avere solo il secondo, perché il minore di due interi sarebbe un numero di tipo reale!



    .....




    .....




    .....




    .....




    .....




    .....




    .....