Sobrecarga de métodos en Java

En esta sección, aprenderá acerca de una de las características más interesantes de Java: la sobrecarga de métodos. En Java, dos o más métodos dentro de la misma clase pueden compartir el mismo nombre, siempre que sus declaraciones de parámetros sean diferentes.

Cuando este es el caso, se dice que los métodos están sobrecargados, y el proceso se denomina sobrecarga de métodos (method overloading). La sobrecarga de métodos es una de las formas en que Java implementa polimorfismo.

1. Cómo sobrecargar un método

En general, para sobrecargar un método, simplemente declare versiones diferentes de él. El compilador se ocupa del resto. Debe observar una restricción importante: el tipo y/o el número de parámetros de cada método sobrecargado debe diferir. No es suficiente que dos métodos difieran solo en sus tipos de devolución.

Los tipos de devolución no proporcionan información suficiente en todos los casos para que Java decida qué método utilizar.

Por supuesto, los métodos sobrecargados también pueden diferir en sus tipos de devolución. Cuando se llama a un método sobrecargado, se ejecuta la versión del método cuyos parámetros coinciden con los argumentos. Aquí hay un ejemplo simple que ilustra la sobrecarga de métodos:

// Programa de demostración de sobrecarga de métodos

class Sobrecarga{
    void demoSobrec(){
        System.out.println("Sin parámetros\n");
    }

    //Sobrecargando demoSobrec para un parámetro int
    void demoSobrec(int a){
        System.out.println("Un parámetro: " +a+"\n");
    }

    //Sobrecargando demoSobrec para dos parámetros int
    int demoSobrec(int a, int b){
        System.out.println("Dos parámetros: "+a+", "+b);
        return a+b;
    }

    //Sobrecargando demoSobrec para dos parámetros double
    double demoSobrec(double a, double b){
        System.out.println("Dos parámetros tipo double: "+a+", "+b);
        return a+b;
    }
}

class DemoSobrecarga{
    public static void main(String[] args) {
        Sobrecarga sc= new Sobrecarga();
        int sumaint;
        double sumadouble;

        //Llamando todas las versiones de demoSobrec
        sc.demoSobrec();

        sc.demoSobrec(2);

        sumaint=sc.demoSobrec(4,6);
        System.out.println("Resultado de demoSobrec(4,6) es: "+sumaint+"\n");

        sumadouble=sc.demoSobrec(1.1,2.2);
        System.out.println("Resultado de demoSobrec(1.1,2.2) es: "+sumadouble);

    }
}

Salida:

Sin parámetros

Un parámetro: 2

Dos parámetros: 4, 6
Resultado de demoSobrec(4,6) es: 10

Dos parámetros tipo double: 1.1, 2.2
Resultado de demoSobrec(1.1,2.2) es: 3.3000000000000003

Como puede ver, está sobrecargado cuatro veces. La primera versión no toma parámetros, la segunda toma un parámetro entero, la tercera toma dos parámetros enteros (int), y la cuarta toma dos parámetros double.

Observe que las primeras dos versiones de ovlDemo() no devuelven nada, y las otras dos devuelven un valor. Esto es perfectamente válido, pero tal como se explicó, la sobrecarga no se ve afectada en un sentido u otro por el tipo de devolución de un método. Por lo tanto, intentar utilizar las dos versiones siguientes de  provocará un error:

void demoSobrec(int a){
   System.out.println("Un parámetro: " +a);
   }

int demoSobrec(int a){
   System.out.println("Un parámetro: " +a);
   return a;
   }

La diferencia en sus tipos de devolución es insuficiente para el propósitos de sobrecarga.

2. Conversiones de tipo automáticas

Como recordará anteriormente en Conversión de tipos de datos, Java proporciona ciertas conversiones de tipo automáticas. Estas conversiones también se aplican a los parámetros de métodos sobrecargados. Por ejemplo, considere lo siguiente:

// Conversiones automáticas de tipo
// en métodos sobrecargados

class Sobrecarga{
   void mitipo (int x){
       System.out.println("Mi tipo (int): "+x);
   }

   void mitipo(double x){
       System.out.println("Mi tipo (double): "+x);
   }

}

class DemoSobrecarga{
    public static void main(String[] args) {
        Sobrecarga sc= new Sobrecarga();

        int i=10;
        double d= 10.1;

        byte b= 99;
        short s=10;
        float f=11.5F;

        sc.mitipo(i);
        sc.mitipo(d);

        sc.mitipo(b); //Conversión de tipo, llamando a sc.mitipo(int)
        sc.mitipo(s); //Conversión de tipo, llamando a sc.mitipo(int)
        sc.mitipo(f); //Conversión de tipo, llamando a sc.mitipo(double)
    }
}

Salida:

Mi tipo (int): 10
Mi tipo (double): 10.1
Mi tipo (int): 99
Mi tipo (int): 10
Mi tipo (double): 11.5

En este ejemplo, sólo dos versiones de están definidos: uno que tiene un parámetro de tipo int y otro que tiene un tipo double. Sin embargo, es posible pasar un valor de tipo byteshort, o float a . En el caso de byte y short, Java automáticamente convierte a int. Así, mitipo(int) se invoca. En el caso de la float, el valor se convierte a double y mitipo(double) es llamado.

Es importante entender, sin embargo, que la conversión automática sólo se aplican si no hay ninguna coincidencia directa entre un parámetro y argumento. Por ejemplo, aquí está el programa anterior con la adición de una versión de f ( ), que especifica un parámetro byte:

class Sobrecarga{

   // Agrego mitipo(byte)
   void mitipo (byte x){
       System.out.println("Mi tipo (byte): "+x);
   }

    void mitipo (int x){
        System.out.println("Mi tipo (int): "+x);
    }

   void mitipo(double x){
       System.out.println("Mi tipo (double): "+x);
   }

}

class DemoSobrecarga{
    public static void main(String[] args) {
        Sobrecarga sc= new Sobrecarga();

        int i=10;
        double d= 10.1;

        byte b= 99;
        short s=10;
        float f=11.5F;

        sc.mitipo(i);
        sc.mitipo(d);

        sc.mitipo(b); //NO HAY CONVERSION DE TIPO
        sc.mitipo(s); //Conversión de tipo, llamando a sc.mitipo(int)
        sc.mitipo(f); //Conversión de tipo, llamando a sc.mitipo(double)
    }
}

Salida:

Mi tipo (int): 10
Mi tipo (double): 10.1
Mi tipo (byte): 99
Mi tipo (int): 10
Mi tipo (double): 11.5

En esta versión, ya que hay una versión de mitipo() que toma un byte de argumento, cuando mitipo() se llama con un byte de argumento, mitipo(byte) se invoca y la conversión automática a int no se produce.

3. Introducción a Polimorfismo

La sobrecarga de métodos soporta el polimorfismo porque es una de las formas en que Java implementa el paradigma de “una interfaz, múltiples métodos“.

Para comprender cómo, considere lo siguiente: En los lenguajes que no admiten la sobrecarga de métodos, a cada método se le debe asignar un nombre único. Sin embargo, frecuentemente querrá implementar esencialmente el mismo método para diferentes tipos de datos.

Considere la función de valor absoluto. En los lenguajes que no admiten la sobrecarga, usualmente hay tres o más versiones de esta función, cada una con un nombre ligeramente diferente. Por ejemplo, en C, la función abs() devuelve el valor absoluto de un entero, labs() devuelve el valor absoluto de un entero largo, y fabs() devuelve el valor absoluto de un valor de coma flotante. Como C no admite sobrecarga, cada función debe tener su propio nombre, aunque las tres funciones hacen esencialmente lo mismo.

Esto hace que la situación sea más compleja, conceptualmente, de lo que realmente es. Aunque el concepto subyacente de cada función es el mismo, todavía tiene tres nombres para recordar. Esta situación no ocurre en Java, porque cada método de valor absoluto puede usar el mismo nombre. De hecho, la biblioteca de clases estándar de Java incluye un método de valor absoluto, llamado abs(). Este método está sobrecargado por la clase Math de Java para manejar todos los tipos numéricos. Java determina qué versión de abs() llamar en función del tipo de argumento.

4. Preguntas Frecuentes

En Java, una firma es el nombre de un método más su lista de parámetros. Por lo tanto, para fines de sobrecarga, no hay dos métodos dentro de la misma clase que puedan tener la misma firma. Tenga en cuenta que una firma no incluye el tipo de devolución, ya que Java no lo utiliza para la resolución de sobrecarga.
La respuesta es ‘Sí’. Podemos tener dos o más métodos estáticos con el mismo nombre, pero se diferencian en los parámetros de entrada.
No podemos sobrecargar dos métodos en Java si difieren solo por palabra clave static (si el número de parámetros y tipos de parámetros es el mismo).
Overloading significa que un mismo método tiene diferentes firmas. Overriding es el mismo método, misma firma pero diferentes clases conectadas a través de la herencia. La sobrecarga es un ejemplo de polimorfismo en tiempo de compilación y la sobreescritura es un ejemplo de polimorfismo en tiempo de ejecución.
Al igual que otros métodos estáticos, sí podemos sobrecargar main() en Java.

Ejemplo: Sobrecarga del método main

class DemoSobrecarga{
    // El método main()
    public static void main(String[] args) {
        System.out.println("Hola Javeros (desde el main)");
        DemoSobrecarga.main("Java");
    }

    // Sobrecargando el método main()
    public static void main(String arg1) {
        System.out.println("Hola, " + arg1);
        DemoSobrecarga.main("Java desde Cero","Sobrecarga de métodos");
    }
    public static void main(String arg1, String arg2) {
        System.out.println("Hola, " + arg1 + ", " + arg2);
    }
}

Salida:

Hola Javeros (desde el main)
Hola, Java
Hola, Java desde Cero, Sobrecarga de métodos

5. Conclusión

Cuando sobrecarga un método, cada versión de ese método puede realizar cualquier actividad que desee. No hay ninguna regla que establezca que los métodos sobrecargados deben relacionarse entre sí. Sin embargo, desde un punto de vista estilístico, la sobrecarga de métodos implica una relación.

Por lo tanto, aunque puede usar el mismo nombre para sobrecargar métodos no relacionados, no debería hacerlo. 

Por ejemplo, podría usar el nombre sqr para crear métodos que devuelvan el cuadrado de un entero y la raíz cuadrada de un valor de coma flotante. Pero estas dos operaciones son fundamentalmente diferentes. Aplicar la sobrecarga de métodos de esta manera frustra su propósito original. En la práctica, debe sobrecargar solo operaciones estrechamente relacionadas.

Comentarios

Entradas populares de este blog

Ejercicios para aprender AutoCAD 3D

Piezas 3D - interesantes

Cómo instalar una fuente de alimentación