Ir al contenido principal

Polimorfismo en JAVA

Así que ya sabes de herencia y control de acceso. Ahora viene el turno del polimorfismo que literal significa muchas formas (ya se que sientes unas incontrolables ganas de aplaudir mi genialidad pero por favor trata de contenerte) el polimorfismo aplica para todo lo que se puede sobre escribir en una relación de herencia, así que la primer pregunta seria ¿y como que se puede sobrescribir en una relación de herencia?. Que tiene una simple y llana respuesta, solo los métodos se pueden sobrescribir así que y esto es para el examen de certificación LAS VARIABLES NO SE SOBRESCRIBEN.

Habiendo aclarado este punto vamos a ver las reglas para sobrescribir un método;

(aclaración método y función son lo mismo así que no te confundas si cambio de la palabra método a la palabra función en el texto)

Para sobrescribir un método no se debe cambiar su signature o en mero castellano la forma en la que fue declarado en la superclase o en la interfaz que lo define, así que lo único que hay que saber es  ¿como respetar la forma en que un método fue declarado?. Para hacer esto primero hay que saber que compone a un metodo;

nivelAcceso tipoRetorno nombreMetodo (tipoArgumento arg.....    ) excepciones 
public           String          unMetodo          (String val1, Double val2) throws IOException

El primer atributo de la declaración de un método es el nivelAcceso para java los niveles de acceso son public, protected, default, private lo primero que se debe saber es LOS MÉTODOS DECLARADOS PRIVATE NO SE SOBRESCRIBEN, lo que nos deja solo tres posibles modificadores para un método que se desea sobrescribir. Aquí la regla es la siguiente, al sobrescribir un método este puede tener igual o menor nivel de restricción así

un método default puede ser sobrescrito como  default, protected o public

void metodo(){}//declarado

void metodo(){}//bien sobrescrito

protected void metodo(){}//bien sobrescrito

public void metodo(){} // bien sobrescrito

un método protected puede ser sobrescrito como   protected o public

 protected void metodo(){}//declarado

 void metodo(){}//mal sobrescrito
 protected void metodo(){}//bien sobrescrito 
public void metodo(){}// bien sobrescrito

un método public puede ser sobrescrito como public  
 
public void metodo(){}// declarado

  void metodo(){}//mal sobrescrito

  protected void metodo(){}//mal sobrescrito 
  public void metodo(){}// bien sobrescrito


El segundo atributo de la declaración de un método es el tipoRetorno que puede ser void (no regresa nada), un tipo primitivo (int, double ,boolean...) o una subclase de Object (String, MiClase....) al momento de sobrescribir un método el tipo de retorno para los casos void y tipo primitivo la regla es que este nunca cambia es decir;

public void metodo(){}

no puede ser sobrescrito como

public Object metodo(){}//no
public int metodo(){}  //no

Así mismo;

public int metodo(){}

no puede ser sobrescrito como

public void metodo() //no
public Integer metodo()//no
public Object metodo()  //no

La única excepción a la regla de sobrescritura para el tipoRetorno son las subclases de Object es decir todos los Objetos declarados en java (con excepción de los declarados final porque esta regla esta relacionada con la herencia y los objetos declarados final no se pueden extender) y es esta
el tipo de valor de retorno al sobrescribir un método puede ser una sublcase (clase que extiende la declarada)del tipo declarado en la definición del método. ejemplo:

Piénsalo así, Object es la superclase de todo los Objetos en java es decir que un metodo con tipo de retorno Object se puede sobrescribir como Object o como cualquier otro tipo de Objeto JAVA

public Object funcion(){}//declaracion

public Object funcion(){}//bien sobre escrito
public String funcion(){}//bien sobrescrito String extiende de Object
public Double funcion(){}//bien sobrescrito Double extiende de Object
public void funcion(){}//MAL la función define un valor de retorno por lo tanto no puede ser void
public double funcion(){}//MAL la función define un valor de retorno tipo objeto y double es primitivo

Segundo ejemplo
 
public Number funcion(){}//declaración

public Object funcion(){}//MAL sobrescrito Number extiende de Object no al revés
public String funcion(){}//MAL sobrescrito String y Number no estan relacionados
public Double funcion(){}//bien sobrescrito Double extiende de Number
public void funcion(){}//MAL la función define un valor de retorno por lo tanto no puede ser void
public double funcion(){}//MAL la función define un valor de retorno tipo objeto y double es primitivo
  
El tercer atributo de la declaración de un método es el nombreMetodo y este nunca cambia aquí lo importante es saber que java es (case sensitive es decir que dado el caso se pone a llorar .. ¿o no?) pues no case sensitive indica que para JAVA Hola es diferente de hola y diferente de hOla y diferente de holA así que si ves esto 
public Number funcion(){}//declaración

public Object fuNcIon(){}//esto es un intento fallido de sobreescritura pero compila

te felicito ahora tienes una clase que funciona perfectamente con dos métodos funcion() y fuNcIon() pero que no tienen nada que ver el uno con el otro.


El cuarto atributo de la declaración de un método es (tipoArgumento arg.....    ) y esta es la definición del conjunto de valores que espera recibir un método, las reglas que aplican para este atributo son bastante estrictas la primera es el numero de argumentos que recibe la función no cambia  la segunda el orden de los valores no cambia y la tercera el tipo de los valores no cambia en especial cuando son Objetos no se puede declarar ni otro tipo de objeto ni una subclase ni una superclase del mismo objeto. El único punto de flexibilidad es que el nombre de las variables puede cambiar.

Cuando se hace cualquiera de los cambios anteriores el resultado no es un error el resultado es un nuevo método que no tiene absolutamente nada que ver con el método que se desea sobrescribir a este resultado se le llama SOBRECARGA 


 public void metodo(String var1, Double var2){}//declaracion

//intento sobrescritura,
public void metodo(Double var2,String var1)
// resultado-> MAL felicitaciones tienes un nuevo metodo que no esta relacionado con el anterior

//intento sobrescritura,
public void metodo(String var1)
// resultado-> MAL felicitaciones tienes un nuevo metodo que no esta relacionado con el anterior

//intento sobrescritura,
public void metodo(String var1, Numeric var2){}
// resultado-> MAL felicitaciones tienes un nuevo metodo que no esta relacionado con el anterior

//intento sobrescritura,
public void metodo(String var1, Double var2, Double var3){}
// resultado-> MAL felicitaciones tienes un nuevo metodo que no esta relacionado con el anterior

//intento sobrescritura,
public void metodo(String var1, double var2){}
// resultado-> MAL felicitaciones tienes un nuevo metodo que no esta relacionado con el anterior
// en este caso cambiaste de un Objeto Double a un tipo primitivo double


//intento sobrescritura,
 public void metodo(String variable1, Double variable2){}
// resultado-> BIEN los nombres de las variables pueden cambiar


Y por ultimo el quinto atributo las excepciones un método al definirse puede declara las excepciones que puede lanzar para advertir a quienes la invoquen de lo que les espera, al momento de sobrescribir un método hay cuatro reglas a tener en cuenta la primera si un método declara un excepción soy libre de declararla o no al momento de sebrescribirlo es decir

public void metodo() throws IOException{}// declaración

public void metodo() {}// sobrescritura, es perfectamente legal  

Puedo sobrescribir la declaración de una excepción con una subclase de la misma pero no con una superclase

public void metodo() throws IOException{}// declaración

public void metodo() {}throws FileNotFoundException// sobrescritura, es perfectamente legal   
// FileNotFoundException extiende de IOException

public void metodo() {}throws Exception//MAL Exception es la superclase de IOException no una //subclase

No puedo agregar nuevas excepciones a menos que sean Runtime Exceptions es decir excepciones que extienden de RuntimeException que son las excepciones inesperadas que suceden en tiempo de ejecucion como un NullPointerException o ArithmeticException.

 public void metodo() throws IOException{}// declaración

public void metodo() throws IOException, NullPointerException{}// sobrescritura, es perfectamente //legal agregar NullPointerException dado que es una RuntimeException


public void metodo() throws FileNotFoundException{}// sobrescritura, es perfectamente legal definir //FileNotFoundException dado que es una subclase de IOException que es la excepcion declarada en //la definición del método

Y la ultima regla; sobrescribir mal las excepciones de un método genera errores de compilación y no puede ser visto como sobrecarga de métodos.

Y eso fue casi todo sobre polimorfismo en JAVA lo importante como siempre es practicar para comprender y poner a prueba todas las reglas nombradas anteriormente

Comentarios

Entradas populares de este blog

Conectarse al LDAP (directorio activo) utilizando JAVA

Un LDAP es un sistema de autenticación estándar utilizado por muchas compañías para controlar el acceso a aplicaciones y recursos. Por lo general se espera que cualquier nueva aplicación haga uso del LDAP para realizar la autenticación y controlar los permisos en forma unificada, la seguridad es transversal a todos los procesos que realiza una organización. Una vez regado el cuento a lo que vinimos, como conectarse a un LDAP. Lo primero que debes saber es que no se requieren librerías adicionales, JAVA en su distribución estandar ya cuenta con todo lo que necesitas. primero tres siglas que tienes que tener en cuanta. CN  = Common Name OU  = Organizational Unit DC  = Domain Component Para conectarse primero necesitas es instanciar un Objeto de la clase LdapContext, este se encargara de manejar la conexión al LDAP y las peticiones que se hagan al mismo. por consiguiente necesitara que le entregues una serie de propiedades de conexión. Esto lo haras con un Map de la siguiente

Clases anónimas JAVA (Anonymous Classes)

Código fuente articulo: https://www.dropbox.com/s/pzw44ot0ji2metl/Lambda.zip?dl=0 Las Clases anónimas en JAVA son una solución rápida para implementar una clase que se va utilizar una vez y de forma inmediata. Por ejemplo el  EventHandler  para un botón se puede implementar en la misma asignación valiendonos de la interfaz  EventHandler  que ya esta definida. Pero mejor vamos con un ejemplo mas simple. De la definición anterior concluimos dos cosas la primera es que para crear una clase anónima es necesario haber definido una interfaz, una clase o una clase abstracta. La clase anónima lo que hará sera implementar la interfaz definida o sobre escribir los métodos definidos. Para ilustrar esto utilizaremos el ejemplo del JAVA Tutorial https://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html . en este ejemplo tenemos que implementar clases que cumpliendo con la interfaz Saludo sean capaces de saludar en diferentes idiomas. El paso uno sera definir la int

Paralelismo en JAVA Executors (ExecutorService, Callables y Futures).

Código fuente articulo: https://www.dropbox.com/s/jci67120hmd0uce/Paralelismo.zip?dl=0 Para manejo de concurrencia Java desde la versión 5 presento el Concurrency API  este presento una mejora substancial en el manejo de hilos y procesos en paralelo, antes solo contabas con Thread y Runnable. lo que te obligaba a controlar la creación y el numero de hilos de ejecución, no te entregaba un resultado del procesamiento y no te dejaba controlar las Excepciones que lanzara un hilo...un hilo se lanzaba y amenos que le enviaras un un CallBack perdías todo contacto con el. Para solucionar este problema se crearon dos tipos de objetos Callables y Futures. estos dos te permiten encapsular una tarea asignándole un tipo de Objeto que sera el valor de retorno y hacer seguimiento a las tareas que ejecuto en paralelo pudiendo preguntar si ya termino, que resultado lanzo y que excepciones ocurrieron. Arranquemos con la implementación de Callable, Callable es una interfaz que te permite defini