Sobreescritura y SobreCarga de Métodos en Java ( Overriding y Overloading )

Iniciado por Expermicid, Noviembre 02, 2014, 05:02:04 PM

Tema anterior - Siguiente tema

0 Miembros y 1 Visitante están viendo este tema.

Sobreescritura y sobrecarga de métodos son 2 conceptos que pueden parecer confusos pero veremos que en sí representan algo muy simple.

Debemos saber que estas propiedades de la Programación Orientada a Objetos nos traen algunas ventajas como por ejemplo la facilidad, extensibilidad y flexibilidad en el código.

Pero que son?

La sobrecarga y sobreescritura no son mas que dos conceptos aplicados al trabajo con métodos, específicamente en el uso que le queremos dar. Estos conceptos dependen principalmente de nuestra lógica de programación y el enfoque o forma de trabajo, depende de lo que queremos hacer. ¿Como así?, veamos de forma mas clara cada concepto.

Sobrecarga de métodos (Overloading)

En java sabemos que si ya declaramos una variable o un método con un nombre en especifico, no podemos declarar otra variable o método que se llame igual, sin embargo esta regla no aplica cuando usamos la Sobrecarga de métodos, ya que esta permite usar el mismo nombre del método pero solo si se tiene diferente firma, ¿firma?, cuando hablamos de la firma de un método, nos referimos a sus parámetros.

En resumen la sobrecarga permite declarar métodos que se llamen igual pero que reciban parámetros diferentes (no pueden haber 2 métodos con el mismo nombre y los mismos parámetros), por esta razón lo que define a que método se ingresa, son los argumentos que se envían como parámetros.

Anteriormente mencioné algo sobre la forma de trabajo o lógica de programación, esto es porque supongamos que yo quiero hacer sumas, pero mi programa debe sumar por aparte 2 números enteros o 2 números doubles, para esto tengo 2 opciones.

1. crear 2 métodos, uno llamado sumaEnteros(int a, int b) y otro sumaDoubles(double a, double b)

2. Aplicar el concepto de sobrecarga, donde aunque también vamos a crear 2 metodos, los vamos a llamar con el mismo nombre pero con diferentes parametros, sumar(int a, int b) y sumar(double a, double b) quedando algo como esto:

Código: java
public void sumar(int a, int b) {
        int suma=a+b;
        System.out.println("la suma es: "+suma);
}
     
public void sumar(double a, double b) {   
        double suma=a+b;
        System.out.println("la suma es: "+suma);
}


Podemos ver que los 2 métodos se llaman igual pero poseen parámetros diferentes, así cuando sean llamados, dependiendo del parámetro enviado se accede al método.

Y no es igual? para que sobrecargar si en ultimas se crea el mismo numero de métodos? 

La pregunta anterior es muy valida y tiene mucha lógica, pero como en otros casos la respuesta también gira en torno a la facilidad, las buenas practicas y la búsqueda de aplicaciones optimizadas. El ejemplo es muy simple y poco complejo, pero imaginemos una aplicación donde se tenga la misma acción pero con procesos diferentes?

Por ejemplo encender un motor y si tenemos diferentes tipos de encendido como el eléctrico, encendido térmico, encendido de combustión etc etc. donde los procesos son muy diferentes pero en ultimas el objetivo es el mismo, pero cada uno necesita ciertas características únicas para encender, aquí podríamos aplicar la sobrecarga para no preocuparnos por llamar los métodos por su nombre sino tan solo llamando al mismo pero enviando los parámetros (características) propios de cada tipo de motor y listo, dependiendo de lo que mandemos java sabrá que motor queremos iniciar.

Sobreescritura de métodos (Overriding)

La Sobreescritura es la forma por la cual una clase que hereda puede re-definir los métodos de su clase Padre, de esta manera puede crear nuevos métodos con el mismo nombre de su superClase.

Es decir, si tengo una clase padre con el método ingresar() yo puedo crear en la clase hija un método que también se llame ingresar() pero implementándolo según lo que necesite (siguiendo obviamente unas reglas que veremos mas adelante) a esto se le llama sobreescritura.

Y para que? si cuando se hereda se pueden usar los métodos de la superClase sin tener que declararlos otra vez, entonces porque sobreescribirlos?

Esta pregunta es muy común, la respuesta es que también depende de lo que queremos hacer, si lo que queremos es extender una funcionalidad por medio de la herencia y si bien, en la clase padre existe el método ingresar(), el método y la lógica que tenga es propia de esa clase, si yo quiero vincularle algo mas a ese método pero que sea especifico para la clase hija, no podría, ya que tendría que modificarlo en la clase padre y de esta manera ya se perdería el enfoque como tal, pues dicha funcionalidad sería común para todas las clases hijas que hereden de la superClase.

Por la razón anterior, la sobreescritura nos permite extender la funcionalidad de un método heredado para hacerlo especifico a lo que necesitemos, pudiendo implementar la lógica que queramos en nuestras clases hijas para el mismo método.

Y cuales son las reglas?

Así como en la sobrecarga nos fijamos en los parámetros, en la sobreescritura nos debemos fijar en que la estructura del método sea igual a la de su superClase, no solo el mismo nombre sino el mismo numero de argumentos y tipo de retorno (o al menos un subtipo de este), así como no tener un nivel de acceso mas restrictivo que el original (que en la clase padre sea protected y en la hija sea private por ejemplo) tampoco se pueden sobreescribir métodos static ni final. (ya que static representa métodos globales y final constantes.)

Algo que también debemos mencionar es que podemos identificar un método sobreescrito cuando tiene la anotación @override, esto es muy común encontrarlo cuando trabajamos con clases abstractas o interfaces, donde se obliga a implementar los métodos de estas si son heredadas o implementadas respectivamente, sin embargo no es obligatorio ponerlo pero si  es recomendable, pues de esta manera el compilador reconoce que se están sobreescribiendo los métodos ayudando a que si nos equivocamos al crear un método distinto, el compilador nos avisaría. Adicionalmente si tenemos la anotación inmediatamente podremos saber que se está aplicando el concepto, algo muy útil cuando trabajamos con código de otras personas.

Veamos un ejemplo donde se sobreescribe el método tocar()

Código: java
Public class Instrumento{
        public String tipo;

        public abstract void tocar() {
                System.out.println("Tocar un Instrumento");
        }
}


class Guitarra extends Instrumento {
        @Override       
        public void tocar() {
                System.out.println("Tocar La Guitarra");
        }
}


Como vemos la clase Guitarra hereda de la clase Instrumento, esta ultima tiene el método tocar() con una implementación diferente a la del método en la clase Guitarra (el mensaje es distinto), al tener la anotación @Override nos damos cuenta que se está sobreescribiendo dicho método y se le puede dar la lógica que queramos especifica para la clase Guitarra.

Ingresar a uno u otro método depende de la lógica del llamado, también es algo muy ligado al polimorfismo donde por medio de este se puede acceder a uno u otro método, por ejemplo si queremos acceder al método tocar() de la clase guitarra aplicando la sobreescritura y el polimorfismo tendríamos que hacer una instancia de la clase padre con un objeto de la clase hija así:

Código: java
Instrumento miGuitarra=new Guitarra();
miGuitarra.tocar();


con esto accederíamos al método tocar de la clase guitarra.

Conclusiones!!!

Como pudimos ver los 2 conceptos son muy similares pero con enfoques totalmente diferentes, en sí el concepto como tal no es confuso y a medida que se va conociendo de a pocos su aplicación tampoco lo será.

Y Listo!!!!! con esto vimos a nivel general lo que representan la sobrecarga y sobreescritura de métodos, recuerden que la forma de dominarles es la práctica y ver su comportamiento con diferentes ejercicios.

Fuente: codejavu

Saludos