Realizzazione della classe BankAccount


Una volta stabilita l'interfaccia pubblica della classe, si può passare alla sua realizzazione.
Occorre dunque scrivere una classe con queste componenti:

 
public class BankAccount { 

   < variabili di istanza > 

   < costruttori >

   < metodi >
}




Variabili di istanza


 
public class BankAccount {

   private double balance;

   < costruttori >

   < metodi >
}




Costruttori

Specifichiamo come costruire i nuovi oggetti implementando i costruttori:

public class BankAccount {
    
    private double balance;
    
    public BankAccount() { 
        balance = 0; 
    }
    
    public BankAccount(double initialBalance) { 
        balance = initialBalance; 
    }
    
    < metodi >
}



Inizializzazione di variabili di istanza



Le variabili di istanza di un oggetto appena costruito possono essere inizializzate in tre modi diversi:
 

  • usando la dichiarazione con inizializzazione
 
public class BankAccount {

   private double balance = 0;
   ...
}
  • usando un costruttore
public class BankAccount {

   private double balance;

   public BankAccount() { 
       balance = 0
   }
   ...
}

  • implicitamente per default: se non si usa alcuna inizializzazione, le variabili di istanza numeriche vengono poste automaticamente a zero. [SCONSIGLIATO!!]



Incapsulamento: public vs. private



 Principio di incapsulamento:
 

Lo stato interno di un oggetto può essere 
letto e modificato solo invocando i suoi metodi.

Le variabili di istanza sono nascoste al programmatore che utilizza una classe, e riguardano solo il programmatore che implementa la classe.


L'idea è di nascondere i dettagli realizzativi, e di fornire metodi per accedere ai dati.

Vantaggio: garanzia che un oggetto non venga posto accidentalmente in uno stato non corretto.



Ad esempio, nella classe BankAccount vogliamo impedire che balance diventi negativo, dobbiamo quindi proteggere la variabile da assegnamenti arbitrari...

Se balance fosse dichiarata public potremmo eseguire i seguenti comandi:

    BankAccount conto = new BankAccount();
    conto.balance = - 1000;

Suggerimento: dichiarare le variabili d'istanza sempre private (o protected, come vedremo quando introdurremo l'ereditarietà...).

 




Metodi

Aggiungiamo infine ai metodi il loro corpo, cioè le istruzioni che devono essere eseguite quando il metodo è invocato: 

public class BankAccount {  
    
    private double balance;  
    
    public BankAccount() { 
        balance = 0; 
    } 
    
    public BankAccount(double initialBalance) { 
        balance = initialBalance; 
    } 
    
    public void deposit(double amount) { 
        balance = balance + amount; 
    } 
    
    public void withdraw(double amount) { 
        double newBalance = balance - amount; 
        if (newBalance >= 0)
            balance = newBalance; 
    } 
    
    public double getBalance() { 
        return balance;  
    } 
    
}

Si noti che nel corpo dei metodi si possono usare sia i parametri formali (amount) che le variabili di istanza (balance) ed eventuali variabili locali (newBalance)


Come sappiamo, il comando

return <espressione>

termina l'esecuzione del metodo e restituisce il valore di  <espressione>  come risultato dell'invocazione del metodo.




BankAccount: versione finale

public class BankAccount {  
    
    private double balance;  
    
    public BankAccount() { 
        balance = 0; 
    } 
    
    public BankAccount(double initialBalance) { 
        balance = initialBalance; 
    } 
    
    public void deposit(double amount) { 
        balance = balance + amount; 
    } 
    
    public void withdraw(double amount) { 
        double newBalance = balance - amount; 
        if (newBalance >= 0)
            balance = newBalance; 
    } 
    
    public double getBalance() { 
        return balance;  
    } 
    
}




Usando la nuova classe

public class BankAccountTest { 

    public static void main(String[] args) {  

        BankAccount account = new BankAccount(10000); 
        
        final double INTEREST_RATE = 5; 
        
        double interest; 
        
        // calcola e aggiunge l'interesse maturato in un anno
        
        interest = account.getBalance() * INTEREST_RATE / 100; 
        account.deposit(interest); 
        
        System.out.println("Balance after year 1 is $"  
                           + account.getBalance()); 
        
        // aggiunge ancora una volta l'interesse  
        
        interest = account.getBalance() * INTEREST_RATE / 100; 
        account.deposit(interest); 
        
        System.out.println("Balance after year 2 is $"  
                           + account.getBalance()); 
    } 
} 

 

Output

Balance after year 1 is $10500.0
Balance after year 2 is $11025.0

 

 




Osservazione: tipi di variabili

Tre diversi tipi di variabili:
  • Variabili locali (es: newBalance).

  • Variabili parametro (o "parametri formali") (es: amount).

  • Variabili di istanza (es: balance).

Le variabili parametro e le variabili locali appartengono ad un metodo. Vengono allocate nel record di attivazione del metodo, e quindi sono eliminate quando il metodo termina l'esecuzione (e il record di attivazione viene disallocato dalla pila). 

Le variabili di istanza appartengono ad un oggetto. Vengono allocate nello heap (come, ad esempio, le variabili che costituiscono un array). Possono essere eliminate dal garbage collector solo quando l'oggetto diventa inaccessibile.


Le variabili vengono inizializzate automaticamente?

Le variabili di istanza e gli elementi di un array, come tutte le variabili allocate nello heap, vengono inizializzate ad un valore predefinito:

  • 0 per le variabili numeriche,
  • false per le variabili booleane,
  • null per le variabili riferimento.

Invece le variabili locali, come tutte le variabili allocate nello stack, devono essere inizializzate esplicitamente dal programma, altrimenti il compilatore segnalerà un errore.


 

Osservazione: parametri impliciti ed espliciti nei metodi

I parametri espliciti di un metodo (statico o di istanza) sono i parametri formali, dichiarati tra parentesi tonde dopo il nome del metodo.

Il parametro implicito di un metodo di istanza è l'oggetto sul quale il metodo viene invocato.

Quando all'interno di un metodo di istanza ci si riferisce ad una variabile di istanza, si intende la variabile di istanza del parametro implicito, ovvero dell'oggetto su cui il metodo è stato invocato.

È possibile accedere al parametro implicito usando la parola chiave this.

Esempi:

public class BankAccount {
         
        ...

   public BankAccount(double balance) {
        this.balance = balance;
   }

   public void deposit(double amount)  {
        this.balance = this.balance + amount;
   }

   public boolean equals(BankAccount conto) {
        return (this.balance == conto.balance);
   }

        ...

}



 

Un esercizio: completare le seguenti classi

public class Persona {

     private static final int ANNO_CORRENTE = 2005;
     private String nome; // variabile d'istanza
     private int annoNascita; // variabile d'istanza

     public String  shownome() { // metodo che restituisce il nome
         ...  }

     public int  showage() { // metodo che restituisce l'eta' 
         ... }

     public Persona(String n, int a) { /* costruttore:
                                          costruisce un oggetto e 
                                          gli assegna nome 
                                          e anno di nascita */
         ... } 
 }




 
public class PersonaTest {

    public static void main (String[] args) {
        /* 
           - stampa "Dimmi un nome";
           - legge la stringa che rappresenta il nome;
           - stampa "Dimmi un anno";
           - legge la stringa che rappresenta l'anno di nascita;
           - costruisce un oggetto persona,
             dandogli nome e anno di nascita da voi scelto; 
           - invoca il metodo shownome() dell'oggetto costruito;
           - invoca il metodo showage() dell'oggetto costruito;
           - stampa la stringa
             "Ho costruito una persona che si chiama ... e ha ... anni "
        */
    }
}