/* *************************************************************************
 * Spesso prima di usare una classe occorre inizializzarla, ad esempio
 * puo' servire di azzerare certe variabili, o allocare della memoria.
 * Allo stesso modo, quando la classe non serve piu', puo' dover essere
 * eseguita qualche operazione di deallocazione della memoria o simili.
 * Cio' si puo' fare scrivendo un metodo che esegua tali funzioni, ma
 * dovremo eseguirlo ogni volta che l'oggetto viene creato:
 *
 * animale cane1 = new animale();    // Ecco che istanzio un animale...
 *
 * cane1.inizializ();		// Chiamiamo il metodo inizializ() di cane1
 *
 * Ci sono 2 inconvenienti: uno e' quello di doversi ricordare ogni volta
 * di chiamare il metodo, col rischio di dimenticarselo e far impazzire
 * tutto; l'altro e' quello di dover ripetere l'operazione meccanicamente
 * per tutti gli oggetti, che possono essere anche decine.
 * Di conseguenza sono stati implementati dei costruttori "automatici",
 * che vengono chiamati alla dichiarazione dell'oggetto senza dover
 * intervenire, e senza che ce ne accorgiamo, a meno che non stampino
 * messaggi.
 * Il costruttore e' un metodo speciale che ha lo stesso nome della classe:
 *
 *    animale() {...}     // Costruttore
 *
 * Da notare che il costruttore non puo' restituire alcun valore, per cui
 * non si fa precedere dal tipo di restituzione (nemmeno da void):
 *
 *  class animale {	   // Definisco la classe animale
 *
 *     private float lunghezza;    // Le variabili private
 *     private int numerozampe;
 *
 *     animale() {        // Il costruttore. Non ha parametri in entrata
 *       lunghezza = 0;
 *       numerozampe = 0;
 *       System.out.println("animale inizializzato");
 *     }                                             // Fine costruttore
 *     ...                           // Altri metodi
 *  }                // Fine classe
 *
 * Nel nostro esempio stampiamo una stringa, ma questo solo per rendere
 * visibile il momento dell'esecuzione del costruttore.
 * Il costruttore viene eseguito quando l'oggetto e' istanziato con "new".
 * Raramente stamperemo inutili messaggi come questi, nella pratica.
 ************************************************************************ */

import java.io.*;         // Include le funzioni I/O standard di base.


/* ********************************************************************** */

public class Jlez7c {            // Da qua inizia la classe Jlez7c

///////////////////////////////////////////////////////////////////////////
//                            Il main...
///////////////////////////////////////////////////////////////////////////

 public static void main(String args[])  // Definiamo il metodo Main.
 {                                       // Inizio del main()

// Ora possiamo dichiarare alcuni oggetti di tipo animale. Durante la
// loro allocazione (tramite new) vengono eseguiti i metodi costruttori

    animale cane1 = new animale();         // ecco che dichiaro 3 animali
    animale cane2 = new animale();         // ossia creo degli esemplari dalla
    animale millepiedi = new animale();    // classe "astratta"

/// Ora dobbiamo mandare un messaggio all'oggetto chiedendogli di modificare
// la sua variabile.

    cane1.mettizampe(4);         // Chiamiamo il metodo mettizampe() di cane1
    cane2.mettizampe(4);         // e quello di cane2, per variare le loro
    millepiedi.mettizampe(1000); // variabili private. Stesso per millepiedi

// Gli altri parametri li chiediamo all'utente.

    System.out.println("\nLunghezza cane 1?");
    cane1.mettilungh(leggiFloat());  // Passa a mettilungh il valore letto.

    System.out.println("Lunghezza cane 2?");
    cane2.mettilungh(leggiFloat());  // Passa a mettilungh il valore letto

    System.out.println("Lunghezza millepiedi?");
    millepiedi.mettilungh(leggiFloat());

    System.out.println("Num. esatto piedi del millepiedi?");
    millepiedi.mettizampe(leggiInt()); // Passa a mettizampe il val. letto.

// Ora visualiziamo lo stato degli animali, usando i loro metodi di lettura.

  System.out.print("\nStato del cane1: zampe = " + cane1.leggizampe());
  System.out.println(", lunghezza = " + cane1.leggilungh());
  System.out.print("\nStato del cane2: zampe = " + cane2.leggizampe());
  System.out.println(", lunghezza = " + cane2.leggilungh());
  System.out.print("\nStato del millepiedi: zampe = " + millepiedi.leggizampe());
  System.out.println(", lunghezza = " + millepiedi.leggilungh());

 }               // Fine del metodo principale Main()

/* -------------------------------------------------------------------------
 * Definiamo un metodo chiamato leggiInt(), che in entrata non ha
 * parametri, e in uscita restituisce un numero intero immesso da tastiera.
 *    int leggiInt()
 * ----------------------------------------------------------------------- */

 public static int leggiInt()
 {
    try {
      DataInputStream leggilo = new DataInputStream(System.in);
      String stringa = leggilo.readLine();     // dichiaro e leggo stringa.
      return(Integer.valueOf(stringa).intValue());  // e la converto in int.
    }
    catch (Exception e) {
      System.out.println("Errore: " + e + " nella lettura da tastiera");
      System.exit(0);
      return(-1);        // Questo return serve solo perche' il metodo
                         // abbia un int di ritorno anche in caso di errore
    }
 }               // Fine di "int leggiInt()"


/* -------------------------------------------------------------------------
 * Definiamo un metodo chiamato leggiFloat(), che in entrata non ha
 * parametri, e in uscita restituisce un numero float immesso da tastiera.
 *    float leggiFloat()
 * ----------------------------------------------------------------------- */

 public static float leggiFloat()
 {
    try {
      DataInputStream leggilo = new DataInputStream(System.in);
      String stringa = leggilo.readLine();     // dichiaro e leggo stringa.
      return(Float.valueOf(stringa).floatValue()); // e la converto in float.
    }
    catch (Exception e) {
      System.out.println("Errore: " + e + " nella lettura da tastiera");
      System.exit(0);
      return(-1);        // Questo return serve solo perche' il metodo
                         // abbia un int di ritorno anche in caso di errore
    }
 }               // Fine di "float leggiFloat()"

}            // Fine della classe Jlez7c

/* *************************************************************************
 * Definiamo la classe animale. Generera' il file animale.class.
 * Il compilatore dara' un warning (attenzione) perche' sarebbe preferibile
 * separare il listato della classe e compilarlo a parte in un file
 * chiamato animale.java. Comunque la compilazione avviene lo stesso.
 ************************************************************************ */

class animale {         // Definisco la classe animale

    private float lunghezza=0;    // Variabile privata
    private int numerozampe=0;    // Variabile privata

    animale() {          // Il costruttore. Non ha parametri in entrata
      lunghezza = 0;
      numerozampe = 0;
      System.out.println("animale inizializzato");
    }                                             // Fine costruttore

// Ora scriviamo i metodi pubblici della classe animale:

/*-------------------------------------------------------------------------*
 * mettilungh: definisce la lunghezza dell'animale.
 *             parametri: in entrata la lunghezza in formato float.
 *-------------------------------------------------------------------------*/

 public void mettilungh(float i)
 {
    lunghezza = i;   // Scrive il valore nella variabile privata "lunghezza".
 }

/*-------------------------------------------------------------------------*
 * mettizampe: definisce il numero di zampe dell'animale.
 *             parametri: in entrata il num. di zampe in formato int.
 *-------------------------------------------------------------------------*/

 public void mettizampe(int l)
 {
    numerozampe = l; // Scrive il valore nella variabile privata "numerozampe".
 }

/*-------------------------------------------------------------------------*
 * leggilungh: legge e restituisce la lunghezza dell'animale.
 *             parametri: in uscita la lunghezza in formato float.
 *-------------------------------------------------------------------------*/

 public float leggilungh()
 {
    return lunghezza;
 }

/*-------------------------------------------------------------------------*
 * leggizampe: legge e restituisce il num. di zampe dell'animale.
 *             parametri: in uscita il num. di zampe in formato int.
 *-------------------------------------------------------------------------*/

 public int leggizampe()
 {
    return numerozampe;
 }

}            // Fine della classe animale


/* *************************************************************************
 * La differenza in output con il listato precedente, e' che prima della
 * domanda "Lunghezza cane 1?" viene stampato:
 *
 * animale inizializzato
 * animale inizializzato
 * animale inizializzato
 *
 * Questo evidenzia il momento in cui sono chiamati i costruttori.
 ************************************************************************* */