Sie sind auf Seite 1von 11

Unidad 4.

Polimorfismo y excepciones
4.1 Definicin de polimorfismo
Polimorfismo
El polimorfismo es un concepto de la programacin orientada a objetos que nos permite programar en forma
general, en lugar de hacerlo en forma especfica. En general nos sirve para programar objetos con
caractersticas comunes y que todos estos compartan la misma superclase en una jerarqua de clases, como si
todas fueran objetos de la superclase. Esto nos simplifica la programacin.
Para ponerlo en prctica se har un ejemplo bastante sencillo. Se har una librera de clases que represente
figuras tridimensionales y bidimensionales, y su respectiva jerarqua de clases. Las clases deben ser capaces
de tener funcionamiento bastante bsico, como obtener reas, volmenes y permetros de la figura
correspondiente.
La representacin de la jerarqua sera como sta:
La superclase de dicha jerarqua podra ser muy parecida a sta:
public abstract class figura {
protected String nombre;
protected int color;
protected int grosorBorde;
public String getNombre(){
return this.nombre;
}
public void setNombre(String n){
this.nombre=n;
}
public int getColor(){
return this.color;
}
public void setColor(int c){
this.color=c;
}
public int getGrosorBorde(){
return this.grosorBorde;
}
public void setGrosorBorde(int g){
this.grosorBorde=g;
}
public abstract void dibujar();
}
Las siguientes clases en el nivel de la jerarqua podran quedar muy parecidas a stas:

public abstract class figura2D extends figura {


public abstract int calcularArea();
public abstract int calcularPerimetro();
}
public abstract class figura3D extends figura {
public abstract int calcularVolumen();
}
El polimorfismo en accin
Supongamos que deseamos saber la figura que tiene mayor rea independientemente de su forma. Primero,
programamos una funcin que halle el mayor de varios nmeros reales positivos.
double valorMayor(double[] x){
double mayor=0.0;
for (int i=0; i<x.length; i++)
if(x[i]>mayor){
mayor=x[i];
}
return mayor;
}
Ahora, la llamada a la funcin valorMayor
double numeros[]={3.2, 3.0, 5.4, 1.2};
System.out.println("El valor mayor es "+valorMayor(numeros));
La funcin figuraMayor que compara el rea de figuras planas es semejante a la funcin valorMayor
anteriormente definida, se le pasa el array de objetos de la clase base Figura. La funcin devuelve una
referencia al objeto cuya rea es la mayor.
static Figura figuraMayor(Figura[] figuras){
Figura mFigura=null;
double areaMayor=0.0;
for(int i=0; i<figuras.length; i++){
if(figuras[i].area()>areaMayor){
areaMayor=figuras[i].area();
mFigura=figuras[i];
}
}
return mFigura;
}
La clave de la definicin de la funcin est en las lneas
if(figuras[i].area()>areaMayor){
areaMayor=figuras[i].area();
mFigura=figuras[i];
}
En la primera lnea, se llama a la versin correcta de la funcin area dependiendo de la referencia al tipo de
objeto que guarda el elemento figuras[i] del array. En areaMayor se guarda el valor mayor de las reas
calculadas, y en mFigura, la figura cuya rea es la mayor.
La principal ventaja de la definicin de esta funcin estriba en que la funcin figuraMayor est definida en
trminos de variable figuras de la clase base Figura, por tanto, trabaja no solamente para una coleccin de

crculos y rectngulos, sino tambin para cualquier otra figura derivada de la clase base Figura. As si se
deriva Triangulo de Figura, y se aade a la jerarqua de clases, la funcin figuraMayor podr manejar objetos
de dicha clase, sin modificar para nada el cdigo de la misma.
Veamos ahora la llamada a la funcin figuraMayor
Figura[] fig=new Figura[4];
fig[0]=new Rectangulo(0,0, 5.0, 7.0);
fig[1]=new Circulo(0,0, 5.0);
fig[2]=new Circulo(0, 0, 7.0);
fig[3]=new Rectangulo(0,0, 4.0, 6.0);
Figura fMayor=figuraMayor(fig);
System.out.println("El rea mayor es "+fMayor.area());
Pasamos el array fig a la funcin figuraMayor, el valor que retorna lo guardamos en fMayor. Para conocer el
valor del rea, desde fMayor se llamar a la funcin miembro area. Se llamar a la versin correcta
dependiendo de la referencia al tipo de objeto que guarde por fMayor. Si fMayor guarda una referencia a un
objeto de la clase Circulo, llamar a la funcin area definida en dicha clase. Si fMayor guarda una referencia
a un objeto de la clase Rectangulo, llamar a la funcin area definida en dicha clase, y as sucesivamente.
La combinacin de herencia y enlace dinmico se denomina polimorfismo. El polimorfismo es, por tanto, la
tcnica que permite pasar un objeto de una clase derivada a funciones que conocen el objeto solamente por su
clase base.
El poder manipular un Objeto como si ste fuera de un tipo genrico otorga mayor flexibilidad al momento de
programar con Objetos, el trmino Polimorfismo tambin es asociado con un concepto llamado Late-Binding
(Ligamiento Tardo), observe el siguiente fragmento de cdigo:
Figura a = new Circulo();
Figura b = new Triangulo();
Inicialmente se puede pensar que este cdigo generara un error debido a que el tipo de referencia es distinta a
la instancia del objeto, sin embargo, el fragmento anterior es correcto y demuestra el concepto de
Polimorfismo; para asentar este tema se describe un ejemplo ms completo:
Uso de Polimorfismo.
El uso de Polimorfismo posee ciertos detalles que no fueron descritos en el ejemplo anterior, uno de estos, que
tambin tiene implicaciones en otros componentes es: Casting.
Uso de "Casting"
El termino "Casting" viene de la palabra "Cast" que significa Molde, por lo que el termino literal es Hacer un
Molde, en Polimorfismo se lleva acabo este proceso de "Casting" implcitamente, una Guitarra se coloca en
el molde de un Instrumento, un Triangulo en el molde de una Figura, sin embargo, en ciertas ocasiones se
requiere realizar un tipo de "Casting" que no es considerado seguro en trminos computacionales.
Anteriormente se mencion que el "Casting" llevado acabo con Polimorfismo es implcito, esto se debe a que
no se requiere de sintaxis especial, simplemente se convierte una Guitarra a un Instrumento, sin embargo,
para llevar una transformacin en sentido opuesto se requiere de sintaxis adicional para mantener la seguridad
de transformacin; analicemos: mientras se puede asegurar que un Triangulo es una Figura ("Up-Casting"),
una Figura no necesariamente es un Triangulo, claro esta que lo puede ser, pero en Java se requiere definir
explcitamente esta operacin ("Down-Casting").
El polimorfismo es una de las cualidades de ms dificil comprensin de la POO. Una de las ventajas de estos
lenguajes es su flexibilidad y el polimorfismo una de las herramientas que potencian esta cualidad. El
polimorfismo tiene un uso muy grfico cuando hacemos uso de la herencia.

El polimorfismo consiste en que toda referencia a un objeto de una clase especfica puede tomar la forma de
una referencia a un objeto de una clase heredada a la suya.
Con el polimorfismo (sig. Varias formas) se consigue que las instancias de una clase padre puedan hacer uso
de las funcionalidades de la clases hijas: misma instancia que se comporta de varias (poli) maneras
(morfismo).
Ejemplo:
Public class Animal(){
public void habla(){
System.out.println("No se que soy");
}
}
Public class Perro() extends Animal{
public void() habla(){
System.out.println("Guau");
}
}
Public class Gato() extends Animal{
public void() habla(){
System.out.println("Miau");
}
}
Public class Zoo(){
public static void main(String[] args) {
Animal animal = new Gato(); animal. Habla(); animal=new Perro(); animal. Habla();
}
}
El resultado por consola sera:
"Miau"
"Guau"

Definicin de excepciones
El trmino excepcin es un forma corta da la frase suceso excepcional y puede definirse de la siguiente
forma.
Una excepcin es un evento que ocurre durante la ejecucin del programa que interrumpe el flujo normal de
las sentencias.
Muchas clases de errores pueden utilizar excepciones desde serios problemas de hardware, como la avera de
un disco duro, a los simples errores de programacin, como tratar de acceder a un elemento de un array fuera
de sus lmites. Cuando dicho error ocurre dentro de un mtodo Java, el mtodo crea un objeto exception y lo
maneja fuera, en el sistema de ejecucin. Este objeto contiene informacin sobre la excepcin, incluyendo su
tipo y el estado del programa cuando ocurri el error. El sistema de ejecucin es el responsable de buscar
algn cdigo para manejar el error. En terminologa java, crear una objeto exception y manejarlo por el
sistema de ejecucin se llama lanzar una excepcin.

4.2 Clases Abstractas

Hay ocasiones, cuando se desarrolla una jerarqua de clases en que algn comportamiento est presente en
todas ellas pero se materializa de forma distinta para cada una. Por ejemplo, pensemos en una estructura de
clases para manipular figuras geomtricas. Podramos pensar en tener una clase genrica, que podra llamarse
FiguraGeometrica y una serie de clases que extienden a la anterior que podran ser Circulo, Poligono, etc.
Podra haber un mtodo dibujar dado que sobre todas las figuras puede llevarse a cabo esta accin, pero las
operaciones concretas para llevarla a cabo dependen del tipo de figura en concreto (de su clase). Por otra parte
la accin dibujar no tiene sentido para la clase genrica FiguraGeometrica, porque esta clase representa una
abstraccin del conjunto de figuras posibles.
Para resolver esta problemtica Java proporciona las clases y mtodos abstractos. Un mtodo abstracto es un
mtodo declarado en una clase para el cual esa clase no proporciona la implementacin (el cdigo). Una clase
abstracta es una clase que tiene al menos un mtodo abstracto. Una clase que extiende a una clase abstracta
debe implementar los mtodos abstractos (escribir el cdigo) o bien volverlos a declarar como abstractos, con
lo que ella misma se convierte tambin en clase abstracta.

Declaracin e implementacin de mtodos abstractos


Siguiendo con el ejemplo del apartado anterior, se puede escribir:
abstract class FiguraGeometrica {
...
abstract void dibujar();
...
}
class Circulo extends FiguraGeometrica {
...
void dibujar() {
// codigo para dibujar Circulo
...
}
}
La clase abstracta se declara simplemente con el modificador abstract en su declaracin. Los mtodos
abstractos se declaran tambin con el mismo modificador, declarando el mtodo pero sin implementarlo (sin
el bloque de cdigo encerrado entre {}). La clase derivada se declara e implementa de forma normal, como
cualquier otra. Sin embargo si no declara e implementa los mtodos abstractos de la clase base (en el ejemplo
el mtodo dibujar) el compilador genera un error indicando que no se han implementado todos los mtodos
abstractos y que, o bien, se implementan, o bien se declara la clase abstracta.
Referencias y objetos abstractos
Se pueden crear referencias a clases abstractas como cualquier otra. No hay ningn problema en poner:
FiguraGeometrica figura;
Sin embargo una clase abstracta no se puede instanciar, es decir, no se pueden crear objetos de una clase
abstracta. El compilador producir un error si se intenta:
FiguraGeometrica figura = new FiguraGeometrica();
Esto es coherente dado que una clase abstracta no tiene completa su implementacin y encaja bien con la idea
de que algo abstracto no puede materializarse.
Sin embargo utilizando el up-casting visto en el captulo dedicado a la Herencia si se puede escribir:

FiguraGeometrica figura = new Circulo(. . .);


figura.dibujar();
La invocacin al mtodo dibujarse resolver en tiempo de ejecucin y la JVM llamar al mtodo de la clase
adecuada. En nuestro ejemplo se llamar al mtodo dibujarde la clase Circulo.

4.3 Reutilizacin del cdigo


Lo primero que se les viene a la cabeza a los estudiantes cuando se les menciona la reutilizacin del cdigo es
el famoso copiar y pegar al que se han acostumbrado en la programacin estructurada, y de hecho muchos lo
hacen en poo, lo cual es una de las practicas que ms encarece el desarrollo de software. Como todo en Java,
el problema se resuelve con las clases. Para reutilizar el cdigo creamos nuevas clases pero, en lugar de partir
de cero, partimos de clases, relacionadas con nuestra clase, que han sido ya creadas y depuradas. El truco est
en
usar
las
clases
sin
ensuciar
el
cdigo
existente.
Una forma de hacer esto es crear objetos de nuestras clases existentes dentro de la nueva clase. Esto se conoce
como composicin porque la nueva clase est compuesta de objetos de clases existentes. Estamos reutilizando
la
funcionalidad
del
cdigo,
y
no
la
forma.
Otra forma es crear una nueva clase como un tipo de una clase ya existente. Tomamos la forma de la clase
existente y aadimos cdigo a la nueva, sin modificar la clase existente. Esta forma de crear nuevos objetos se
llamada herencia, y lo que hacemos es extender la clase en la que nos basamos para crear la nueva.
Hasta ahora hemos usado la composicin de cierta manera, ej. cuando hacemos una interfaz grfica de
usuario, nuestra clase de interfaz grfica esta compuesta por un frame, unos panel, botones, etc. todos estos
objetos componen el objeto de interfaz grfica. Es decir que la composicin consiste en poner manejadores de
objetos dentro de nuestra clase, estos manejadores de objetos no sern otra cosa que instancias de las clases en
las que nos estamos basando para crear la nueva clase.
Recordemos que la forma para determinar cundo usar composicin es cuando podemos decir que nuestra
nueva clase tiene un elemento de otro tipo de objetos, por ejemplo un cronmetro tiene: horas, minutos y
segundos, es decir que una clase Cronometro est compuesta por otras clases llamadas: Horas, Minutos y
Segundos.
Veamos como seria esta clase:
public class Cronometro {
Horas h;
Minutos m;
Segundos s;
String cadena;
int seg,min,hor;
public Cronometro() {
seg=0;

min=0;
hor=0;
h = new Horas();
m = new Minutos();
s = new Segundos();
cadena = new String("0 : 0 : 0");
}
public String avanzar(){
seg = s.forward();
if(seg==0){
min=m.forward();
if(min==0){
hor=h.forward();
}
}
cadena = hor + " : " + min + " : " + seg;
return cadena;
}
public String reset(){
seg = s.reset();
min = m.reset();
hor = h.reset();
cadena = hor + " : " + min + " : " + seg;
return cadena;
}
}
Nuestra clase Cronometro est compuesta entre otras cosas por objetos del tipo Horas, Minutos y Segundos y
a travs del constructor de nuestra clase creamos las instancias de cada una de ellas.
Herencia
En java aunque no establezcamos de manera explcita la herencia siempre est presente, ya que todas las
clases que creemos heredan de la clase Object, por eso es vlido decir que en java todo es un objeto. La
sintaxis para la composicin es obvia pero, para realizar la herencia, hay una forma claramente distinta.
Cuando heredamos, estamos diciendo "Esta nueva clase es como esa clase antigua", por ejemplo es decir que
la clase Horas es una UnidadDeTiempo. Afirmamos esto en el cdigo dando el nombre de la clase como
siempre pero, antes de la apertura del lmite cuerpo de clase, pondremos la palabra clave "extends" seguida
por el nombre de la clase base. Cuando hagamos esto, obtendremos automticamente todos los datos
miembros
y
mtodos
de
la
clase
base.

Primero veamos como seria la clase UnidadDeTiempo:


public class UnidadDeTiempo {
int valor;
int tope;
public int forward(){
if(valor == tope)
valor=0;
else
valor++;
return valor;
}
public int reset(){
valor=0;
return valor;
}
}
Y nuestra clase Horas:
public class Horas extends UnidadDeTiempo{
public Horas() {
this.valor=0;
this.tope=23;
}
}
De esta manera sin necesidad de tener que escribir nuevamente todos el cdigo de UnidadDeTiempo lo
tememos disponible en la clase Horas, pero que partes tenemos disponibles?, todos los atributos y los mtodos
de la clase padre estn disponibles en la clase hija pero dependiendo de los modificadores de acceso o
visibilidad de estos, por ejemplo los atributos y mtodos de tipo friendly solo estarn disponibles para las
clases hijas que heredan de una clase padre en el mismo paquete, los atributos y mtodos de tipo public
estarn disponibles para todas las clases que hereden de la clase padre sin importar que se halle o no en el
mismo paquete; los miembros protected tambin son accesibles desde las clases hijas.
El cdigo de nuestra clases hijas no tienen porque limitarse solo al cdigo heredado, de hecho casi siempre la
herencia se hace para extender la funcionalidad de las clases heredadas aadiendo nuevos mtodos y
atributos.

La composicin y la herencia

Tanto la composicin como la herencia permiten poner sub-objetos dentro de tu nueva clase. Podramos
preguntarnos cul es la diferencia entre los dos, y cundo elegir uno en lugar del otro. La composicin es
generalmente usada cuando deseamos las caractersticas de una clase existente dentro de una nueva clase,
pero no su interfaz. Es decir, ponemos un para poder usarlo para implementar caractersticas de nuestra nueva
clase, pero el usuario de esa nueva clase ver el interfaz que hemos definido en lugar del interfaz del objeto
insertado.
Los objetos miembros usan la implementacin ocultndose a s mismos, por lo que esto es una cosa segura a
hacer y, cuando el usuario sabe que estamos uniendo un conjunto de partes, hace que el interfaz sea ms fcil
de entender.

Cuando heredamos, estamos cogiendo una clase existente y creando una versin especial de esa clase. En
general, esto significa que estamos tomando una clase de propsito general, especializndola para un caso o
necesidad particular. Pensando un poco, podr entender que no tendra sentido construir un coche usando un
objeto vehculo (un coche no contiene un vehculo, es un vehculo!). La relacin es- un viene expresada por
la herencia, y la relacin tiene un viene expresada por la composicin.

4.4 Tipos de excepciones


Existen varios tipos fundamentales de excepciones:

Error: Excepciones que indican problemas muy graves, que suelen ser no recuperables y no deben
casi nunca ser capturadas.

Exception: Excepciones no definitivas, pero que se detectan fuera del tiempo de ejecucin.

RuntimeException: Excepciones que se dan durante la ejecucin del programa.

Todas las excepciones tienen como clase base la clase Throwable, que est incluida en el paquete java.lang, y
sus mtodos son:

Trowable( String mensaje ); Constructor. La cadena es opcional

Throwable fillInStackTrace(); Llena la pila de traza de ejecucin.

String getLocalizedMessage(); Crea una descripcin local de este objeto.

String getMessage(); Devuelve la cadena de error del objeto.

Void printStackTrace( PrintStream_o_PrintWriter s ); Imprime este objeto y su traza en el flujo


del parmetro s, o en la salida estndar (por defecto).

String toString; Devuelve una breve descripcin del objeto.

4.5 Gestin de excepciones


Las excepciones son el mecanismo por el cual pueden controlarse en un programa Java las condiciones de
error que se producen. Estas condiciones de error pueden ser errores en la lgica del programa como un ndice
de un array fuera de su rango, una divisin por cero o errores disparados por los propios objetos que
denuncian algn tipo de estado no previsto, o condicin que no pueden manejar.

La idea general es que cuando un objeto encuentra una condicin que no sabe manejar crea y dispara una
excepcin que deber ser capturada por el que le llam o por alguien ms arriba en la pila de llamadas. Las
excepciones son objetos que contienen informacin del error que se ha producido y que heredan de la clase
Throwable o de la clase Exception. Si nadie captura la excepcin interviene un manejador por defecto que
normalmente imprime informacin que ayuda a encontrar quin produjo la excepcin.
Existen dos categoras de excepciones:

Excepciones verificadas: El compilador obliga a verificarlas. Son todas las que son lanzadas
explicitamente por objetos de usuario.

Excepciones no verificadas: El compilador no obliga a su verificacin. Son excepciones como


divisiones por cero, excepciones de puntero nulo, o ndices fuera de rango.

Generacion de exepciones

Supongamos que tenemos una clase Empresa que tiene un array de objetos Empleado (clase vista en captulos
anteriores). En esta clase podramos tener mtodos para contratar un Empleado (aadir un nuevo objeto al
array), despedirlo (quilarlo del array) u obtener el nombre a partir del nmero de empleado. La clase podra
ser algo as como lo siguiente:
public class Empresa {
String nombre;
Empleado [] listaEmpleados;
int totalEmpleados = 0;
...
Empresa(String n, int maxEmp) {
nombre = n;
listaEmpleados = new Empleado [maxEmp];
}
...
void nuevoEmpleado(String nombre, int sueldo) {
if (totalEmpleados < listaEmpleados.length ) {
listaEmpleados[totalEmpleados++] = new Empleado(nombre,sueldo);
}
}
}
Observese en el mtodo nuevoEmpleado que se comprueba que hay sitio en el array para almacenar la
referencia al nuevo empleado. Si lo hay se crea el objeto. Pero si no lo hay el mtodo no hace nada ms. No
da ninguna indicacin de si la operacin ha tenido xito o no. Se podra hacer una modificacin para que, por
ejemplo el mtodo devolviera un valor booleano true si la operacin se ha completado con xito y false si ha
habido algn problema.

Otra posibilidad es generar una excepcin verificada (Una excepcin no verificada se producira si no se
comprobara si el nuevo empleado va a caber o no en el array). Vamos a ver como se hara esto.
Las excepciones son clases, que heredan de la clase genrica Exception. Es necesario por tanto asignar un
nombre a nuestra excepcin. Se suelen asignar nombres que den alguna idea del tipo de error que controlan.
En nuestro ejemplo le vamos a llamar CapacidadEmpresaExcedida.
Para que un mtodo lance una excepcin:

Debe declarar el tipo de excepcin que lanza con la clusula throws, en su declaracin.

Debe lanzar la excepcin, en el punto del cdigo adecuado con la sentencia throw.

En nuestro ejemplo:
void nuevoEmpleado(String nombre, int sueldo) throws CapacidadEmpresaExcedida {
if (totalEmpleados < listaEmpleados.length) {
listaEmpleados[totalEmpleados++] = new Empleado(nombre,sueldo);
}
else throw new CapacidadEmpresaExcedida(nombre);
}
Adems, necesitamos escribir la clase CapacidadEmpresaExcedida. Sera algo as:
public class CapacidadEmpresaExcedida extends Exception {
CapacidadEmpresaExcedida(String nombre) {
super("No es posible aadir el empleado " + nombre);
}
...
}
La sentencia throw crea un objeto de la clase CapacidadEmpresaExcedida . El constructor tiene un argumento
(el nombre del empleado). El constructor simplemente llama al constructor de la superclase pasndole como
argumento un texto explicativo del error ( y el nombre del empleado que no se ha podido aadir).
La clase de la excepcin puede declarar otros mtodos o guardar datos de depuracin que se consideren
oportunos. El nico requisito es que extienda la clase Exception. Consultar la documentacin del API para ver
una descripcin completa de la clase Exception.
De esta forma se pueden construir mtodos que generen excepciones.

Das könnte Ihnen auch gefallen