domingo, 26 de febrero de 2012

4.1 Definicion de polimorfismo

Para descargar el documento del tema, haz clic aquí

Polimorfismo

El polimorfismo es un concepto de la programación orientada a objetos que nos permite programar en forma general, en lugar de hacerlo en forma específica. En general nos sirve para programar objetos con características comunes y que todos estos compartan la misma superclase en una jerarquía de clases, como si todas fueran objetos de la superclase. Esto nos simplifica la programación.

Para ponerlo en práctica se hará un ejemplo bastante sencillo. Se hará una librería de clases que represente figuras tridimensionales y bidimensionales, y su respectiva jerarquía de clases. Las clases deben ser capaces de tener funcionamiento bastante básico, como obtener áreas, volúmenes y perímetros de la figura correspondiente.

La representación de la jerarquía sería como ésta:


.





La superclase de dicha jerarquía podría 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 jerarquía podrían 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();
}






Supongamos que deseamos saber la figura que tiene mayor área independientemente de su forma. Primero, programamos una función que halle el mayor de varios números 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 función valorMayor
               double numeros[]={3.2, 3.0, 5.4, 1.2};
               System.out.println("El valor mayor es "+valorMayor(numeros));
La función figuraMayor que compara el área de figuras planas es semejante a la función valorMayor anteriormente definida, se le pasa el array de objetos de la clase base Figura. La función 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 definición de la función está en las líneas
           if(figuras[i].area()>areaMayor){
                areaMayor=figuras[i].area();
                mFigura=figuras[i];
            }

En la primera línea, se llama a la versión correcta de la función 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 definición de esta función estriba en que la función figuraMayor está definida en términos de variable figuras de la clase base Figura, por tanto, trabaja no solamente para una colección de círculos y rectángulos, sino también para cualquier otra figura derivada de la clase base Figura. Así si se deriva Triangulo de Figura, y se añade a la jerarquía de clases, la función figuraMayor podrá manejar objetos de dicha clase, sin modificar para nada el código de la misma.
Veamos ahora la llamada a la función 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 función figuraMayor, el valor que retorna lo guardamos en fMayor. Para conocer el valor del área, desde fMayor se llamará a la función miembro area. Se llamará a la versión 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 función area definida en dicha clase. Si fMayor guarda una referencia a un objeto de la clase Rectangulo, llamará a la función area definida en dicha clase, y así sucesivamente.
La combinación de herencia y enlace dinámico se denomina polimorfismo. El polimorfismo es, por tanto, la técnica 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 genérico otorga mayor flexibilidad al momento de programar con Objetos, el término Polimorfismo también es asociado con un concepto llamado Late-Binding (Ligamiento Tardío), observe el siguiente fragmento de código:
     Figura a = new Circulo();
     Figura b = new Triangulo();
Inicialmente se puede pensar que este código generaría 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 más completo:
Uso de Polimorfismo.
El uso de Polimorfismo posee ciertos detalles que no fueron descritos en el ejemplo anterior, uno de estos, que también 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" implícitamente, 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 términos computacionales.
Anteriormente se mencionó que el "Casting" llevado acabo con Polimorfismo es implícito, esto se debe a que no se requiere de sintaxis especial, simplemente se convierte una Guitarra a un Instrumento, sin embargo, para llevar una transformación en sentido opuesto se requiere de sintaxis adicional para mantener la seguridad de transformación; 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 explícitamente esta operación ("Down-Casting").

El polimorfismo es una de las cualidades de más dificil comprensión 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 gráfico cuando hacemos uso de la herencia.
El polimorfismo consiste en que toda referencia a un objeto de una clase específica 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"

1 comentario: