/* *************************************************************************
 * Nei listati fino ad ora abbiamo creato delle classi, ma non abbiamo avuto
 * mai modo di istanziare una nostra classe nel main di un'altra classe.
 * Come abbiamo visto, ogni classe crea un file .class col nome della
 * classe stessa. Se si definiscono piu' classi nello stesso sorgente.java,
 * da esso dopo la compilazione verranno creati i vari file class.
 * La separazione delle classi quindi e' proprio "fisica": files diversi!
 * Abbiamo visto che una classe si crea in questo modo:
 *
 * [accesso] [modificatori] class nomeclasse { ... }
 *
 * In [accesso] si puo' facoltativamente mettere public, protected o
 * private, che determinano la visibilita' della classe rispetto alle
 * altre. In altre parole determinano il livello di accesso.
 * Una classe/variabile/metodo PUBLIC e' visibile da tutte le classi
 * esterne, ossia i metodi delle altre classi possono accederci.
 * Dichiarare tutto public semplifica le cose ai principianti, ma rende
 * piu' pericoloso il lavoro agli esperti.
 * Che livello di protezione viene assegnato se non si mette niente?
 * ad esempio se si scrive semplicemente "int i;" o "class bau{..}"?
 * Si ha un livello di protezione simile a public, ma un po' piu'
 * ristretto, in quanto non si puo' accedere dal di fuori del package..
 * Comunque non e' possibile specificare "manualmente" questo tipo di
 * accesso con una parola chiave, l'unico modo e non metterne alcuna.
 * Non abbiamo ancora spiegato bene i package, quindi sorvoliamo.
 * Un po' piu' restrittivo e' l'accesso di tipo PROTECTED, che permette
 * l'accesso solo alla stessa classe e alle classi derivate, figlie.
 * Attenzione al fatto che occorre scrivere PRIVATE PROTECTED, e non
 * solo PROTECTED per ottenere questo livello di protezione.
 * Il livello di protezione piu' alto e' PRIVATE, che rende visibili
 * metodi e variabili soltanto alle classi in cui sono definite.
 * Tutto cio' che non serve alle classi esterne e che non deve essere
 * condiviso con esse, deve essere reso private, in modo da rendere
 * effettivamente impossibile un caso di accesso dall'esterno.
 * Rese private queste variabili, saranno utilizzabili dalle classi
 * esterne attraverso i metodi pubblici della classe, mai direttamente.
 * Molto semplicemente, dovremo definire 2 classi anziche' 1 nel prossimo
 * sorgente: la prima sara' quella principale, con il main(), nella
 * quale istanzieremo oggetti della seconda classe.
 * Il nostro scopo e' di entrare nella filosofia object oriented un po'
 * meglio di quanto abbiamo fatto fino ad ora. Definire tutti i metodi e
 * le variabili come public e/o static porta a usare il Java come un
 * lunguaggio non OO, e cio' limita molto le sue possibilita'.
 * Vediamo quindi l'uso di una classe con dati privati e metodi pubblici.
 * Ricordiamoci di istanziare gli oggetti con l'operatore "new".
 ************************************************************************* */

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


// La classe Jlez7b e' quella da eseguire, che conterra' il main() e
// che istanziera' un oggetto dalla classe animale. Da notare che
// questo sorgente crea due file: Jlez7b.class e animale.class

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

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

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

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

// Ora possiamo dichiarare alcuni oggetti di tipo animale e usarli:

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

// Non possiamo accedere direttamente ai dati degli oggetti, sono privati.
// Con cane1.numerozampe = 4 otterremmo un errore di compilazione.
// 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

//  cane1.numerozampe = 4;       // Abilitate questa istruzione illegale
                                 // per ottenere un errore in compilazione.

// 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 Jlez7b

/* *************************************************************************
 * Definiamo la classe animale. Generera' il file animale.class.
 * Il compilatore dara' un warning (attenzione) nel caso che la classe
 * fosse public, 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

// 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


/* *************************************************************************
 * Questo e' il nostro primo programma diviso in 2 file .class.
 * Provate a togliere il // all'istruzione che scrive illegalmente nella
 * variabile privata di un istanza di animale, e noterete come in fase
 * di compilazione si presenti un errore, con tanto di testo esplicativo.
 * Avrete notato come ogni metodo sia preceduto da un campo di commento
 * in cui si definisce chiaramente il suo scopo, e in particolare
 * i parametri in entrata ed uscita. Il programma funziona anche senza
 * commenti, ma con essi diventa comprensibile anche ad altri, e a noi,
 * nel caso si rispolverasse dopo anni, una volta dimenticato tutto.
 * Purtroppo molti non commentano assolutamente i listati, e cio' lo credo
 * un errore grave quanto quelli che causano malfunzionamenti.
 ************************************************************************* */