Conceptos sobre polimorfismo y programación orientada a objetos

El polimorfismo, en programación orientada a objetos, se refiere a la posibilidad de acceder a un variado rango de funciones distintas a través del mismo interfaz. O sea, un mismo identificador puede tener distintas formas (distintos cuerpos de función, distintos comportamientos) dependiendo del contexto en el que se halle. El polimorfismo se puede establecer mediante sobrecarga, sobre-escritura y enlace dinámico.

Sobrecarga

Este término se refiere al uso del mismo identificador u operador en distintos contextos y con distintos significados.

Si para cada funcionalidad necesitada fuese necesario escribir un método, el código resultante sería inmanejable. Supongamos que los desarrolladores de Java hubiesen creado un método para escribir en pantalla una cadena de texto, otro diferente para escribir un entero, otro para un doble, y así para todas las combinaciones posibles, seria casi imposible conocer dichos métodos en totalidad. En cambio, con “System.out.print()” o “System.out.println()” podemos escribir cualquier mensaje en pantalla.

Este tipo de codificación nos es permitido gracias a la sobrecarga, la cual se aplica a métodos y constructores.

La sobrecarga de métodos hace que un mismo nombre pueda representar distintos métodos con distinto tipo y número de parámetros, manejados dentro de la misma clase. En el ámbito de la POO, la sobrecarga de métodos se refiere a la posibilidad de tener dos o más métodos con el mismo nombre pero distinta funcionalidad. Es decir, dos o más métodos con el mismo nombre realizan acciones diferentes y el compilador usará una u otra dependiendo de los parámetros usados. Esto también se aplica a los constructores (de hecho, es la aplicación más habitual de la sobrecarga).

Podemos diferenciar varios métodos sobrecargados a través de sus parámetros, ya sea por la cantidad, el tipo o el orden de los mismos. Veamos un ejemplo:

public class Articulo {

	private float precio;

	public void setPrecio() {
		precio = 3.50;
	}
	public void setPrecio(float nuevoPrecio) {
		precio = nuevoPrecio;
	}
	public void setPrecio(float costo, int porcentajeGanancia) {
		precio = costo + (costo * porcentajeGanancia);
	}
}

Sobreescritura

La sobreescritura se aplica a los métodos y está directamente relacionada a la herencia; se refiere a la redefinición de los métodos de la clase base en las subclases. Por ejemplo, en la relación de herencia del ejemplo de las figuras aunque la clase base “Figura” tiene los métodos “calcularArea” y “calcularPerimetro”, las subclases “Circulo”, “Cuadrado”, “Triangulo” y “Rectangulo” redefinen estos métodos ya que el calculo del área y el perímetro de cada uno de ellos es diferente.

class Figura {

     protected double area;
     protected double perimetro;

     public Figura() {
       this.area=0;
         this.perimetro=0;
     }
     public double getArea() {
         return area;
     }
     public double getPerimetro() {
         return perimetro;
     }
     public void calcularArea(){}
     public void calcularPerimetro(){}
}

public class Circulo extends Figura {

     private double radio;

     public Circulo() {
         super();
     }
     public double getRadio() {
         return radio;
     }
     public void setRadio(double radio) {
         this.radio = radio;
     }
     public void calcularArea() {
       this.area = Math.PI*Math.pow(this.radio,2.0);
     }
     public void calcularPerimetro() {
       this.perimetro = 2*Math.PI*this.radio;
 }
}

Enlace dinámico

Esto permite invocar operaciones en objetos obviando el tipo actual de éstos hasta el momento de ejecutar el código. O sea, nos permite definir elementos como un tipo e instanciarlos como un tipo heredado. Pero ¿qué utilidad tiene obviar el tipo de un objeto para luego tomar esta decisión?.

Gracias a que en java la definición de los tipos de objetos se puede producir por enlazado posterior (late binding), no nos debe preocupar a qué tipo de elemento le paso un mensaje, ya que el compilador tomará la decisión sobre qué objeto ejecutará qué método de acuerdo a la forma de crear la instancia.

Este concepto es bastante complejo de entender, ya que estamos acostumbrados a definir los elementos de acuerdo a lo que necesitamos. Es decir, si requiero un entero lo declaro como entero; ¿para que declarar un elemento como un tipo y luego usarlo como otro?. La respuesta está en que no siempre se puede determinar exactamente el tipo de elemento que va a usarse en la ejecución de nuestro programa.

Se debe tener por lo menos una relación de herencia que permita determinar un tipo base para la declaración, sea cual sea el subtipo que se instancie. Veamos un ejemplo que nos aclare un poco las cosas:

class Mamifero {
  public void mover() {
    System.out.println("Ahora es un mamifero el que se mueve");
  }
}

class Perro extends Mamifero {
  public void mover() {
    System.out.println("Ahora es un perro el que se mueve");
  }
}

class Gato extends Mamifero {
  public void mover() {
    System.out.println("Ahora es un gato el que se mueve");
  }
}

public class Polimorfismo {
  public static void muevete(Mamifero m) {
    m.mover();
  }
  public static void main(String[] args) {
    Gato bisho = new Gato();
    Perro feo = new Perro();
    muevete(bisho);
    muevete(feo);
  }
}

Vemos que el método “muevete” llama al método mover de un mamífero y aunque no sabe con qué clase de mamífero trata, funciona y se llama al método correspondiente al objeto específico que lo llama (es decir, primero un gato y luego un perro). Si no existiera el enlace dinámico, tendríamos que crear un método “muevete” para los mamíferos de tipo “Gato” y otro para los de tipo “Perro”.

Veamos otro ejemplo donde las instancias se crean de forma aleatoria:

public abstract class Instrumento {
     public Instrumento() { }
     public abstract void tocar();
     public abstract void tocar(String nota);
 public abstract void afinar();
}

public class Cuerda extends Instrumento{
 public Cuerda() {}
      public void afinar() {
         System.out.println("Cuerda.afinar()");
     }
 public void tocar() {
         System.out.println("Cuerda.tocar()");
     }
     public void tocar(String nota){
         System.out.println("Cuerda.tocar()"+nota);
     }
}

public class Percusion extends Instrumento{
     public Percusion() {}
     public void afinar() {
         System.out.println("Percusion.afinar()");
     }
     public void tocar() {
         System.out.println("Percusion.tocar()");
     }
     public void tocar(String nota){
         System.out.println("Percusion.tocar()"+nota);
     }
}

public class Viento extends Instrumento{
     public Viento() {}
     public void afinar() {
         System.out.println("Viento.afinar()");
     }
     public void tocar() {
         System.out.println("Viento.tocar()");
     }
     public void tocar(String nota){
         System.out.println("Viento.tocar()"+nota);
     }
}

public class LigaduraDinamica {
    public static void main(String[] args){
        String[] notas = {"Do","Re","Mi","Fa","Sol","La","Si"};
        Instrumento orquesta[] = new Instrumento[10];

        for(int i=0;i<10;i++){
            orquesta[i]=generarInstrumento(new java.util.Random().nextInt(3));
        }

        for(int i=0;i<10;i++){
            afinarInstrumento(orquesta[i]);
        }

        for(int i=0;i<10;i++){
            tocarInstrumento(orquesta[i]);
        }

        for(int i=0;i<10;i++){
            tocarInstrumento(orquesta[i],notas[i%7]);
        }
    }

    public static Instrumento generarInstrumento(int i){
        switch(i){
        default:
        case 0:
            return new Viento();
        case 1:
            return new Percusion();
        case 2:
            return new Cuerda();
        }
    }

    public static void afinarInstrumento(Instrumento o){
        o.afinar();
    }

    public static void tocarInstrumento(Instrumento o){
        o.tocar();
    }

     public static void tocarInstrumento(Instrumento o,String nota){
        o.tocar(nota);
    }
}

Vemos que el método “generarInstrumento” crea aleatoriamente las instancias de los diferentes tipos de instrumentos y que el arreglo de elementos del tipo de instrumentos es llenado con diferentes elementos de los cuales sólo sabemos que son objetos basados en “Instrumento”. Sin embargo, los métodos “tocarInstrumento” y “afinarInstrumento” que reciben como parámetro un Instrumento llaman adecuadamente a los métodos “afinar” o “tocar” según la instancia que reciben.

Visto en Programación orientada a objetos.

OT:hasta ahora, no conocía la posibilidad de usar la etiqueta sourcecode de WordPress:

(o php, o python o…), la cual mejora muchísimo la presentación del código fuente. El editor de WP tiene el botón para <code>, pero es una castaña, por lo que venía usando hasta ahora las etiquetas <pre>, pero, literalmente, no hay color 😛 .

15 Comments »

  1. 1
    Vanesa Says:

    muy buen sitio, bastante completo y excelente ejemplo gracias por esto 😀

    Like

  2. 2
    VERO Says:

    muy bueno el articulo, me sirvio mucho!! gracias!!!! 🙂

    Like

  3. 3
    Edwin Cuenca Says:

    MUY BUENA LA CONSULTA… GRACIAS…

    Like

  4. 4
    Alexandra Says:

    muy bena me sirvió de mucho GRACIAS

    Like

  5. 5
    Fernando Says:

    Excelente! me ayudo mucho en mi exposición gracias 😀

    Like

  6. 6
    kelly Says:

    eso no ,me ayudo ni pio para hacer mi tarea osea que no me ayudo

    Like

  7. 7

    muuyy buenooo

    Like

  8. 8
    mayi chavez Says:

    bueno aunque muy largo

    Like

  9. Genial!!!
    No lo había entendido nunca -ni siquiera en Youtube-…
    Infinitas Gracias!

    Like

  10. 10
    Angie Says:

    Según mi apreciación el primer ejemplo está mal, definen dos veces la clase Perro, en lugar de definir, Perro y Gato

    class Perro extends Mamifero {

    public void mover() {
    System.out.println("Ahora es un perro el que se mueve");
    }
    }

    Porfa háganme saber si ésto es correcto o no 🙂

    De antemano gracias.

    Like

  11. 12
    asdasdas Says:

    bien copiado de otro blog, al menos podrias citar la fuente ….

    Like

  12. 14
    aosjfpsadf Says:

    Like

  13. 15
    aosjfpsadf Says:

    alert(“xss”);

    Like


RSS Feed for this entry

Leave a comment