/* *************************************************************************
 * Pensate a come risolvere questo problema: dobbiamo sommare 3 coppie di
 * variabili di 3 tipi diversi: int,long,float. In C occorre scriversi 3
 * funzioni di somma, una per gli int, una per i long, e una per i float:
 *
 *   int sommainteri(int a,int b) {...}
 *   long sommalong(long c,long d) {...}
 *   float sommafloat(float a,float b) {...}
 *
 * In seguito, nel programma, dobbiamo stare attenti ad usare la funzione
 * giusta a seconda del tipo da sommare:
 *
 *   bau = sommafloat(miofloat1,miofloat2);
 *   beu = sommalong(miolong1,miolong2);
 *   bou = sommaint(mioint1,mioint2);
 *
 * Se poi le mie variabili si chiamano sbirulino, scarrafone, ecc., dovro'
 * anche andarmi a cercare ogni volta nel listato la dichiarazione per
 * ricordarmi il loro tipo, per usare la funzione giusta.
 * In Java, invece, grazie al polimorfismo, possiamo sovrapporre metodi
 * aventi lo stesso nome, purche' abbiano parametri diversi: in questo
 * modo, possiamo riscrivere i 3 metodi visti prima dandogli lo stesso nome:
 *
 * int somma(int a,int b) {...}
 * long somma(long c,long d) {...}
 * float somma(float e,float f) {...}
 *
 * Attenzione al fatto che vengono considerati solo i tipi dei parametri
 * (int,long,float), non i nomi delle variabili (a,b,c): se si scrivono
 * due metodi come questi:
 *
 * int somma(int a,int b) {...}
 * int somma(int c,int d) {...}
 *
 * Facciamo una cosa illegale, in quanto i due metodi sono equivalenti,
 * avendo gli stessi tipi nei parametri.
 * Questa sovrapposizione (overloading), ci permette ora di scrivere in
 * modo molto piu' semplice il listato, usando somma() per tutti i casi:
 *
 * bau = somma(miofloat1,miofloat2);
 * beu = somma(miolong1,miolong2);
 * bou = somma(mioint1,mioint2);
 *
 * Questo approccio e' migliore dal punto di vista logico, infatti quando
 * programmiamo e sommiamo la variabile X con la variabile Y, spesso non
 * ci ricordiamo il tipo di queste ultime, non essendo fondamentale, ma
 * se dobbiamo usare funzioni diverse a seconda del tipo, allora siamo
 * costretti a far entrare nel nostro ragionamento anche questo, facendoci
 * distrarre. Se dovessimo usare degli operatori diversi a seconda del
 * tipo di numeri anche quando facciamo i conti a mente, ad esempio dovessimo
 * pensare: "1 piuintero 1 = 2", "1 piufloat 1 = 2", allora fare i conti
 * della spesa diventerebbero difficili anche per un prof. di matematica.
 * Invece, grazie al polimorfismo, si puo' "scaricare" questo compito al
 * compilatore, lasciando a noi i problemi piu' seri.
 * Da notare che il tipo di valore restituito dal metodo (ritorno) non
 * conta quando il compilatore deve scegliere che overload chiamare: per
 * tale scopo sono presi in considerazione solo i parametri in entrata.
************************************************************************ */

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


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

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

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

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

    int mioint1 = 15;        // Variabile di tipo int
    int mioint2 = 50;        // Variabile di tipo int

    long miolong1 = 150000;  // variabile di tipo long
    long miolong2 = 1666000; // variabile di tipo long

// Per indicare i numeri "float" occorre aggiungere una F finale.
// Se non si specifica niente, si indicano i double (se col ".") o int.

    float miofloat1 = 3.02f;  // Variabile di tipo float
    float miofloat2 = 32.24f; // Variabile di tipo float

// Ora sommiamo coppie di variabili di 3 tipi diversi usando sempre somma()

    System.out.print(mioint1 + " + " + mioint2 + " = ");
    System.out.println(somma(mioint1,mioint2));

    System.out.print(miolong1 + " + " + miolong2 + " = ");
    System.out.println(somma(miolong1,miolong2));

    System.out.print(miofloat1 + " + " + miofloat2 + " = ");
    System.out.println(somma(miofloat1,miofloat2));

 }               // Fine del metodo principale Main()

/* Ecco i 3 metodi aventi lo stesso nome e parametri diversi, che grazie
 * al polimosfismo si overloadano (soprappongono): ogni volta verra'
 * chiamato automaticamente il metodo giusto a seconda del tipo.
*/

 public static int somma(int a,int b)
 {
    return(a+b);
 }

// Ora la versione per i long

 public static long somma(long c,long d)
 {
    return(c+d);
 }

// Infine la versione per i float

 public static float somma(float e,float f)
 {
    return(e+f);
 }

}            // Fine della classe Jlez8a


/* *************************************************************************
 * L'overloading permette di accedere ad un unsieme di metodi simili (almeno
 * a livello logico) usando lo stesso nome.
 * Naturalmente un'altra comodita' del polimorfismo e' quella di aggiungere
 * dei parametri opzionali ad una funzione.
 ************************************************************************ */