viernes, 18 de marzo de 2011

Fase2 - Actividad2 - UML y Conceptos bàsicos de POO


  1. Qué es un Actor?
Se le llama actor a toda entidad externa al sistema que guarda una relación con éste y que le demanda una funcionalidad. Esto incluye a los operadores humanos pero también incluye a todos los sistemas externos, además de entidades abstractas, como el tiempo.
En el caso de los seres humanos se pueden ver a los actores como definiciones de rol, por lo que un mismo individuo puede corresponder a uno o más Actores. Suele suceder sin embargo, que es el sistema quien va a tener interés en el tiempo. Es frecuente encontrar que nuestros sistemas deben efectuar operaciones automáticas en determinados momentos; y siendo esto un requisito funcional obvio, resulta de interés desarrollar alguna forma de capturar dicho requisito en el modelo de caso de uso final.
  1. Qué es un rol?
Es la función que cumple un objeto para lo que fue diseñado, o la función que alguien cumple, para lo cual fue contratado a hacer en una labor determinada.
Roles en UML
UML distingue entre roles estáticos y roles dinámicos. Los primeros son los roles de extremo de una asociación, utilizados para referirse al papel específico que juega una clase cuando participa en cierta asociación con otra, es decir tienen el mismo significado que en el modelo entidad-relación. Los roles dinámicos son los que participan en las colaboraciones y puesto que, en principio, corresponden a la definición de rol de la sección anterior, vamos a centrarnos en ellos.
  1.   Cuantos roles puede tener un usuario?
Un usuario puede tener diferentes roles de acuerdo al papel que asuma cada miembro. Se observa como cada miembro siempre aporta ideas y como suelen decidir o actuar.
  1. Para quien están dirigidos los diagramas de casos de uso?
Va dirigido a cada actor que está unido a los casos de uso en los que participa.
El caso de uso es una descripción de la secuencia de interacciones que se producen entre un actor y el sistema, cuando el actor usa el sistema para llevar a cabo una tarea específica. Expresa una unidad coherente de funcionalidad, y se representa en el Diagrama de Casos de Uso mediante una elipse con el nombre del caso de uso en su interior. El nombre del caso de uso debe reflejar la tarea específica que el actor desea llevar a cabo usando el sistema.
  1. Cuantos niveles de Diagramas de Casos de uso existen y menciónelos.
Depende de los que el sistema necesite
  1. Qué hacer cuando el diagrama de caso de uso es muy grande y no cabe en una sola hoja?
Hay que tratar de leerlo en un solo diagrama, o dividirlo en módulos diferentes para que se pueda entender desde el de mayor importancia hasta el de menor importancia.
  1. Cuando se tiene un diagrama de casos de uso muy complejo qué recomendarías?
Recomendaría dividirlo en varios módulos de manera que sea más fácil de asimilar

CLASE:  definiciones de las propiedades y comportamiento de un tipo de objeto concreto. La instanciación es la lectura de estas definiciones y la creación de un objeto a partir de ellas.
Ejemplo:
¿Qué es una clase?
Una clase es algo abstracto que define la "forma" del objeto, se podría hablar de la clase como el molde de los objetos.
En el mundo real existen objetos del mismo tipo, por ejemplo tu bicicleta es solo una mas de todas las bicicletas del mundo. Entonces diríamos que tu bicicleta es una instancia de la clase "Bicicleta". Todas las bicicletas tienen los atributos: color, cantidad de cambios, dueño y métodos: acelerar, frenar, pasar cambio, volver cambio.
Las fábricas de bicicletas utilizan moldes para producir sus productos en serie, de la misma forma en POO utilizaremos la clase bicicleta (molde) para producir sus instancias (objetos).
Los objetos son instancias de clases.
Ejemplo: Podríamos tener la clase Perro, una instancia de esta clase podría ser el objeto perro llamado "Chicho". La clase Perro especificaría que todos los perros tendrían un nombre, color de pelo, una altura. Mientras que la instancia "Chicho" contendrá valores específicos para cada uno de estos atributos.
Podemos definir a una clase como una plantilla que define variables y métodos comunes para todos los objetos de cierto tipo.
Existe un lenguaje de modelado llamado UML mediante el cual podemos representar gráficamente todo un sistema orientado a objetos utilizando rectángulos, líneas y otro tipo de símbolos gráficos. Según UML, la clase "Cuenta Bancaria" antes mencionada se representará gráficamente como sigue:

Mensajes

Un objeto por si solo no tiene mucho significado. Ejemplo: el objeto "bicicleta" no tiene mucho sentido si no interactúa con un objeto "persona" que pedalee.
La interacción entre objetos se produce mediante mensajes. Los mensajes son llamados a métodos de un objeto en particular.
Podemos decir que el objeto persona envía el mensaje "girar a la izquierda" al objeto bicicleta.
Los mensajes pueden contener parámetros. Por ejemplo teniendo un método en la clase bicicleta llamado "Girar" que recibe como parámetro la dirección (derecha o izquierda).
Un mensaje está compuesto por los siguientes tres elementos:
1.     El objeto destino, hacia el cual el mensaje es enviado
2.     El nombre del método a llamar
3.     Los parámetros solicitados por el método

Beneficios de los mensajes

Como todo lo que un objeto puede hacer esta expresado mediante métodos, el envío de mensajes soporta todas las posibles interacciones entre objetos.
Para enviar o recibir mensajes, los objetos no necesitan formar parte del mismo proceso, ni siquiera de la misma máquina.

INSTANCIA: Definición y ejemplo
Instancia. Se crea cuando una construye un objeto. Las instancias de una clase comparten los mismo atributos pero pueden diferir en qué los atributos contengan. Por ejemplo una clase “Persona” describe los atributos comunes de una persona; cada persona es generalmente parecida, pero varía en atributos como “altura” y “peso”. La clase listaría tipos de atributos, así como también las acciones que una persona podría realizar: “saltar”, “caminar”, “andar”, “comer”. La instancia es el objeto creado en tiempo de corrida de una aplicación. Otro ejemplo sería: “Lassie” es una instancia de la clase “Perro” y así también “Pluto” sería otra instancia de la misma clase.

OBJETO: Objeto. Se refiere comúnmente a atributos (elementos) y comportamientos (métodos) encapsulados en una entidad. Son un método natural para implementar estructuras de datos abstractos, trayendo “físicamente” componentes de datos con procedimientos para luego manipularlos. Todo objeto tiene estado, exhibe un comportamiento bien definido y posee identidad única.

Ejemplo:

¿Qué es un objeto?

Objeto es el concepto clave de la Programación Orientada a Objetos, la idea de objeto es similar a la del mundo real, un objeto puede ser una silla, una mesa. Tu perro es un objeto.
Los objetos tienen dos características: Un estado y un comportamiento. Fijate que por ejemplo tu perro tiene un estado: nombre, color, raza, altura, etc. y un comportamiento: ladrar, cavar pozo, llorar, dormir, comer, etc.
Un auto es un objeto. También tiene un estado: Cantidad de puertas, color, tamaño, etc. y un comportamiento: acelerar, frenar, subir cambio, bajar cambio, girar izq., girar der., etc.
Entonces podemos definir a un objeto en POO, como un conjunto de datos y funciones relacionadas. A las funciones de los objetos, tales como acelerar en el caso del auto, de aquí en más las llamaremos métodos, a los datos los llamaremos atributos.
Los objetos en programación, son modelados observando objetos del mundo real, por ejemplo implementamos el objeto "perro" dentro de nuestro programa definiendo los atributos y métodos del objeto perro real.
El objeto "Auto" se puede representar gráficamente como sigue:


 Instancia: significa: Solicitud o Insistencia.
Una instancia de un programa es una copia de una versión ejecutable del programa que ha sido escrito en la memoria del computador.
Una instancia de un programa es creada típicamente por el click de usuario en un icono de una interfaz Gráfica para usuarios GUI o por la entrada de un comando en una interfaz de línea de comandos CLI y presionando la tecla ENTER. Instancias de programas pueden ser creadas por otros programas.
 ejemplo de instancia: en un lenguaje de programación visual, sería tomar o arrastrar un objeto de la barra de herramientas o de la lista de librerías y colocarlo en el escritorio o escenario de trabajo (estamos creando una instancia de ese objeto, una copia). Si arrastramos 10 botones al entorno visual de trabajo, estamos creando una instancia del botón original, si a cada botón le cambiamos el nombre, tendremos 10 botones que heredan las mismas propiedades y métodos del objeto original. Tenemos como resultado que con un solo botón hicimos 10 y nuestro archivo pesara como si tuviese uno solo.

UML: Lenguaje Unificado de Modelado (LUM o UML, por sus siglas en inglés, Unified Modeling Language) es el lenguaje demodelado de sistemas de software más conocido y utilizado en la actualidad; está respaldado por el OMG (Object Management Group). Es un lenguaje gráfico para visualizar, especificar, construir y documentar un sistema. UML ofrece un estándar para describir un "plano" del sistema (modelo), incluyendo aspectos conceptuales tales como procesos de negocio y funciones del sistema, y aspectos concretos como expresiones de lenguajes de programación, esquemas de bases de datos y componentes reutilizables.
Se puede aplicar en el desarrollo de software entregando gran variedad de formas para dar soporte a una metodología de desarrollo de software (tal como el Proceso Unificado Racional o RUP), pero no especifica en sí mismo qué metodología o proceso usar.
UML no puede compararse con la programación estructurada, pues UML significa Lenguaje Unificado de Modelado, no es programación, solo se diagrama la realidad de una utilización en un requerimiento. Mientras que, programación estructurada, es una forma de programar como lo es la orientación a objetos, sin embargo, la programación orientada a objetos viene siendo un complemento perfecto de UML, pero no por eso se toma UML sólo para lenguajes orientados a objetos.
UML cuenta con varios tipos de diagramas, los cuales muestran diferentes aspectos de las entidades representadas.
Cómo es la estructura de un objeto y cómo se representa en UML:
Ejemplo:
Diagramas
Jerarquía de los diagramas UML 2.0, mostrados como un diagrama de clases
En UML 2.0 hay 13 tipos diferentes de diagramas. Para comprenderlos de manera concreta, a veces es útil categorizarlos jerárquicamente, como se muestra en la figura de la derecha.
Los Diagramas de Estructura enfatizan en los elementos que deben existir en el sistema modelado:
Los Diagramas de Comportamiento enfatizan en lo que debe suceder en el sistema modelado:
Los Diagramas de Interacción son un subtipo de diagramas de comportamiento, que enfatiza sobre el flujo de control y de datos entre los elementos del sistema modelado:

Encapsulación:
En programación modular, y más específicamente en programación orientada a objetos, se denomina encapsulamiento al ocultamiento del estado, es decir, de los datos miembro, de un objeto de manera que sólo se puede cambiar mediante las operaciones definidas para ese objeto.
Cada objeto está aislado del exterior, es un módulo natural, y la aplicación entera se reduce a un agregado o rompecabezas de objetos. El aislamiento protege a los datos asociados a un objeto contra su modificación por quien no tenga derecho a acceder a ellos, eliminando efectos secundarios e interacciones.
De esta forma el usuario de la clase puede obviar la implementación de los métodos y propiedades para concentrarse sólo en cómo usarlos. Por otro lado se evita que el usuario pueda cambiar su estado de maneras imprevistas e incontroladas.

Encapsulamiento
Se dice que es el empaquetado de métodos y atributos dentro de un objeto, mediante una interfaz grafica. La clave está precisamente en el envoltorio del objeto .
Como se puede observar de los diagramas, las variables del objeto se localizan en el centro o núcleo del objeto. Los métodos rodean y esconden el núcleo del objeto de otros objetos en el programa. Al empaquetamiento de las variables de un objeto con la protección de sus métodos se le llama encapsulamiento. Típicamente, el encapsulamiento es utilizado para esconder detalles de la puesta en práctica no importantes de otros objetos. Entonces, los detalles de la puesta en práctica pueden cambiar en cualquier tiempo sin afectar otras partes del programa.
El encapsulamiento de variables y métodos en un componente de software ordenado es, todavía, una simple idea poderosa que provee dos principales beneficios a los desarrolladores de software: El encapsulamiento consiste en unir en la Clase las características y comportamientos, esto es, las variables y métodos. Es tener todo esto en una sola entidad. En los lenguajes estructurados esto era imposible. Es evidente que el encapsulamiento se logra gracias a la abstracción y el ocultamiento que veremos a continuación. La utilidad del encapsulamiento va por la facilidad para manejar la complejidad, ya que tendremos a las Clases como cajas negras donde sólo se conoce el comportamiento pero no los detalles internos, y esto es conveniente porque lo que nos interesará será conocer qué hace la Clase pero no será necesario saber cómo lo hace.
La encapsulación da lugar a que las clases se dividan en dos partes:
  1. Interface: captura la visión externa de una clase, abarcando la abstracción del comportamiento común a los ejemplos de esa clase.
  2. Implementación: comprende la representación de la abstracción, así como los mecanismos que conducen al comportamiento deseado.




ENCAPSULAMIENTO: introducción 1


  • El principio de encapsulamiento es una forma moderna de denominar al tradicional principio de ocultamiento de la información. El principio nos indica que debemos hacer que los detalles de la clase estén ocultos para el exterior (también se denomina implementación encapsulada).
Es un principio de la ingeniería en general. Si estamos diseñando un equipo de música no parece adecuado que permitamos al usuario operar sobre las placas para cambiar el volumen o el tono. Los botones del equipo son el interfaz del sistema, la implementación queda encapsulada (oculta).



ENCAPSULAMIENTO: introducción 2

Visión externa (interfaz): class CUBO {
Definición del mensaje ...

ENCAPSULAMIENTO: introducción 3
  • Algunas definiciones:
“Consiste en separar los aspectos externos del objeto, a los cuales puede acceder otro objeto, de los detalles internos de implementación, que quedan ocultos para los demás” (RUMBAUGH, 1991)
“El encapsulamiento es el proceso de almacenar en un mismo compartimento los elementos de una abstracción que constituyen su estructura y comportamiento; sirve para separar el interfaz contractual de una abstracción y su implementación” (BOOCH, 1994)

ENCAPSULAMIENTO DE CLASES
  • Siguiendo la metáfora del equipo de música debemos diferenciar en nuestras clases lo que es público de lo que es privado.
  • Una aplicación general de este principio implica que los atributos serán privados y sólo se puede acceder a ellos desde los métodos públicos de la clase.
  • Ventaja: desde el código de la clase controlamos el acceso a los atributos. En caso de fallo o modificación del código, el programador comprueba los métodos de la clase que modifican ese dato y no tiene que revisar todo el código de los otros archivos. Además evitamos accesos indeseados que puedan modificarlos de forma no coherente con otros datos. Los métodos públicos son el intermediario (interfaz) entre los datos y los otros objetos:
Objetos


ENCAPSULAMIENTO: ocultar estructuras y algoritmos internos
  • Las estructuras de datos que utiliza una clase internamente (por ejemplo un vector o un árbol) no deben ser accesibles para otras clases.
  • Por la misma razón los algoritmos internos deben quedar ocultos. Por ejemplo, la mayor parte de las modernas librerías de software tienen métodos para ordenar listas. Desde fuera el programador solo debe conocer el interfaz del método y lo que hace. No accedemos al interior del algoritmo:
/* Llamo al método static sort() de la clase Collections, le
paso como primer arg la lista y como segundo arg un objeto comparador */
Collections.sort( lista, new comparador() );


Abstraccion:
La abstracción consiste en aislar un elemento de su contexto o del resto de los elementos que lo acompañan. En programación, el término se refiere al énfasis en el "¿qué hace?" más que en el "¿cómo lo hace?" (característica de caja negra). El común denominador en la evolución de los lenguajes de programación, desde los clásicos o imperativos hasta los orientados a objetos, ha sido el nivel de abstracción del que cada uno de ellos hace uso.
Uso
A grandes rasgos, la abstracción, permite que dispongamos de las características de un objeto que necesitemos. Si necesitamos el objeto Persona, podríamos poner nombre, edad, dirección, estado civil, etc. Si lo necesitamos en un sistema administrativo, pero, si lo requerimos para el área de biología, dentro de sus atributos quizá tengamos, ADN, RND, Gen x1, Gen x2, etc. Y los atributos antes mencionados no sean requeridos. En general, podemos decir que Persona cuenta con todos los atributos mencionados aquí, pero, por el proceso de abstracción excluimos todos aquellos, que no tiene cabida en nuestrosistema.

Ejemplo

Pensar en términos de objetos es muy parecido a cómo lo haríamos en la vida real. Una analogía sería modelizar un coche en un esquema de POO. Diríamos que el coche es el elemento principal que tiene una serie de características, como podrían ser el color, el modelo o la marca. Además tiene una serie de funcionalidades asociadas, como pueden ser ponerse en marcha, parar o aparcar. En un esquema POO el coche sería el objeto, las propiedades serían las características como el color o el modelo y los métodos serían las funcionalidades asociadas como ponerse en marcha o parar.
Por poner otro ejemplo vamos a ver cómo modelizaríamos en un esquema POO una fracción, es decir, esa estructura matemática que tiene un numerador y un denominador que divide al numerador, por ejemplo 3/2. La fracción será el objeto y tendrá dos propiedades, el numerador y el denominador. Luego podría tener varios métodos como simplificarse, sumarse con otra fracción o número, restarse con otra fracción, etc.
Estos objetos son utilizables en los programas, por ejemplo en un programa de matemáticas se puede hacer uso de objetos fracción y en un programa que gestione un taller de coches, objetos coche. Los programas orientados a objetos utilizan muchos objetos para realizar las acciones que se desean realizar y ellos mismos también son objetos. Es decir, el taller de coches será un objeto que utilizará objetos coche, herramienta, mecánico, recambios, etc.


Relación:
Concepto del término relación: 1. En bases de datos, una relación o vínculo entre dos o más entidades describe alguna interacción entre las mismas.













Modularidad Modular:
La programación modular es un paradigma de programación que consiste en dividir un programa en módulos o subprogramas con el fin de hacerlo más legible y manejable.
Se presenta históricamente como una evolución de la programación estructurada para solucionar problemas de programación más grandes y complejos de lo que ésta puede resolver.
Al aplicar la programación modular, un problema complejo debe ser dividido en varios subproblemas más simples, y estos a su vez en otros subproblemas más simples. Esto debe hacerse hasta obtener subproblemas lo suficientemente simples como para poder ser resueltos fácilmente con algún lenguaje de programación. Ésta técnica se llama refinamiento sucesivo, divide y vencerás ó análisis descendente (Top-Down).
Un módulo es cada una de las partes de un programa que resuelve uno de los subproblemas en que se divide el problema complejo original. Cada uno de estos módulos tiene una tarea bien definida y algunos necesitan de otros para poder operar. En caso de que un módulo necesite de otro, puede comunicarse con éste mediante una interfaz de comunicación que también debe estar bien definida.
Si bien un modulo puede entenderse como una parte de un programa en cualquiera de sus formas y variados contextos, en la práctica es común representarlos con procedimientos y funciones. Adicionalmente, también pueden considerarse módulos las librerías que pueden incluirse en un programa o, en programación orientada a objetos, la implementación de un tipo de dato abstracto.

¿Qué es programación modular?

Uno de los métodos más conocidos para resolver un problema es dividirlo en problemas más pequeños, llamados subproblemas. De esta manera, en lugar de resolver una tarea compleja y tediosa, resolvemos otras más sencillas y a partir de ellas llegamos a la solución. Esta técnica se usa mucho en programación ya que programar no es más que resolver problemas, y se le suele llamar diseño descendente, metodología del divide y vencerás o programación top-down.
Es evidente que si esta metodología nos lleva a tratar con subproblemas, entonces también tengamos la necesidad de poder crear y trabajar con subprogramas para resolverlos. A estos subprogramas se les suele llamar módulos, de ahí viene el nombre deprogramación modular. En Pascal disponemos de dos tipos de módulos: los procedimientos y las funciones.
Veamos un ejemplo de cómo emplear el diseño descendente para resolver un problema. Supongamos que un profesor quiere crear un programa para gestionar las notas de sus alumnos. Quiere que dicho programa le permita realizar tareas tales como asignar notas, cambiar notas, ver las notas según distintas calificaciones, etc. A continuación tines un esquema que representa una de las posibles divisiones del problema en módulos.

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 distintosvalores 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:
01
public class Articulo {
02


03
    private float precio;
04


05
    public void setPrecio() {
06
        precio = 3.50;

07
    }
08
    public void setPrecio(float nuevoPrecio) {

09
        precio = nuevoPrecio;
10
    }

11
    public void setPrecio(float costo, int porcentajeGanancia) {
12
        precio = costo + (costo * porcentajeGanancia);

13
    }
14
}

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.
01
class Figura {
02


03
     protected double area;
04
     protected double perimetro;

05

06
     public Figura() {

07
       this.area=0;
08
         this.perimetro=0;

09
     }
10
     public double getArea() {

11
         return area;
12
     }

13
     public double getPerimetro() {
14
         return perimetro;

15
     }
16
     public void calcularArea(){}

17
     public void calcularPerimetro(){}
18
}

19

20
public class Circulo extends Figura {

21

22
     private double radio;

23

24
     public Circulo() {

25
         super();
26
     }

27
     public double getRadio() {
28
         return radio;

29
     }
30
     public void setRadio(double radio) {

31
         this.radio = radio;
32
     }

33
     public void calcularArea() {
34
       this.area = Math.PI*Math.pow(this.radio,2.0);

35
     }
36
     public void calcularPerimetro() {

37
       this.perimetro = 2*Math.PI*this.radio;
38
 }

39
}

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:
01
class Mamifero {
02
  public void mover() {

03
    System.out.println("Ahora es un mamifero el que se mueve");
04
  }

05
}
06


07
class Perro extends Mamifero {
08
  public void mover() {

09
    System.out.println("Ahora es un perro el que se mueve");
10
  }

11
}
12


13
class Perro extends Mamifero {
14
  public void mover() {

15
    System.out.println("Ahora es un gato el que se mueve");
16
  }

17
}
18


19
public class Polimorfismo {
20
  public static void muevete(Mamifero m) {

21
    m.mover();
22
  }

23
  public static void main(String[] args) {
24
    Gato bisho = new Gato();

25
    Perro feo = new Perro();
26
    muevete(bisho);

27
    muevete(feo);
28
  }

29
}
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:
01
public abstract class Instrumento {
02
     public Instrumento() { }

03
     public abstract void tocar();
04
     public abstract void tocar(String nota);

05
 public abstract void afinar();
06
}

07

08
public class Cuerda extends Instrumento{

09
 public Cuerda() {}
10
      public void afinar() {

11
         System.out.println("Cuerda.afinar()");
12
     }

13
 public void tocar() {
14
         System.out.println("Cuerda.tocar()");

15
     }
16
     public void tocar(String nota){

17
         System.out.println("Cuerda.tocar()"+nota);
18
     }

19
}
20


21
public class Percusion extends Instrumento{
22
     public Percusion() {}

23
     public void afinar() {
24
         System.out.println("Percusion.afinar()");

25
     }
26
     public void tocar() {

27
         System.out.println("Percusion.tocar()");
28
     }

29
     public void tocar(String nota){
30
         System.out.println("Percusion.tocar()"+nota);

31
     }
32
}

33

34
public class Viento extends Instrumento{

35
     public Viento() {}
36
     public void afinar() {

37
         System.out.println("Viento.afinar()");
38
     }

39
     public void tocar() {
40
         System.out.println("Viento.tocar()");

41
     }
42
     public void tocar(String nota){

43
         System.out.println("Viento.tocar()"+nota);
44
     }

45
}
46


47
public class LigaduraDinamica {
48
    public static void main(String[] args){

49
        String[] notas = {"Do","Re","Mi","Fa","Sol","La","Si"};
50
        Instrumento orquesta[] = new Instrumento[10];

51

52
        for(int i=0;i<10;i++){

53
            orquesta[i]=generarInstrumento(new java.util.Random().nextInt(3));
54
        }

55

56
        for(int i=0;i<10;i++){

57
            afinarInstrumento(orquesta[i]);
58
        }

59

60
        for(int i=0;i<10;i++){

61
            tocarInstrumento(orquesta[i]);
62
        }

63

64
        for(int i=0;i<10;i++){

65
            tocarInstrumento(orquesta[i],notas[i%7]);
66
        }

67
    }
68


69
    public static Instrumento generarInstrumento(int i){
70
        switch(i){

71
        default:
72
        case 0:

73
            return new Viento();
74
        case 1:

75
            return new Percusion();
76
        case 2:

77
            return new Cuerda();
78
        }

79
    }
80


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

83
    }
84


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

87
    }
88


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

91
    }
92
}
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.

Definición de polimorfismo
La palabra polimorfismo proviene del griego y significa que posee varias formas diferentes. Este es uno de los conceptos esenciales de una programación orientada a objetos. Así como la herencia está relacionada con las clases y su jerarquía, el polimorfismo se relaciona con los métodos.
En general, hay tres tipos de polimorfismo:
Trataremos de describir ahora con más precisión estos tipos de polimorfismo, pero le sugerimos prestar atención, ya que muchas personas suelen confundirse al tratar de comprender las diferencias existentes entre estos tres tipos.
Polimorfismo de sobrecarga
El polimorfismo de sobrecarga ocurre cuando las funciones del mismo nombre existen, con funcionalidad similar, en clases que son completamente independientes una de otra (éstas no tienen que ser clases secundarias de la clase objeto). Por ejemplo, la clase complex, la clase image y la clase link pueden todas tener la función "display". Esto significa que no necesitamos preocuparnos sobre el tipo de objeto con el que estamos trabajando si todo lo que deseamos es verlo en la pantalla.
Por lo tanto, el polimorfismo de sobrecarga nos permite definir operadores cuyos comportamientos varían de acuerdo a los parámetros que se les aplican. Así es posible, por ejemplo, agregar el operador + y hacer que se comporte de manera distinta cuando está haciendo referencia a una operación entre dos números enteros (suma) o bien cuando se encuentra entre dos cadenas de caracteres (concatenación).
Polimorfismo paramétrico
El polimorfismo paramétrico es la capacidad para definir varias funciones utilizando el mismo nombre, pero usando parámetros diferentes (nombre y/o tipo). El polimorfismo paramétrico selecciona automáticamente el método correcto a aplicar en función del tipo de datos pasados en el parámetro.
Por lo tanto, podemos por ejemplo, definir varios métodos homónimos de addition() efectuando una suma de valores.
  • El método int addition(int,int) devolvería la suma de dos números enteros.
  • float addition(float, float) devolvería la suma de dos flotantes.
  • char addition(char, char) daría por resultado la suma de dos caracteres definidos por el autor.
  • etc.
Una signature es el nombre y tipo (estático) que se da a los argumentos de una función. Por esto, una firma de método determina qué elemento se va a llamar.
Polimorfismo de subtipado
La habilidad para redefinir un método en clases que se hereda de una clase base se llamaespecialización. Por lo tanto, se puede llamar un método de objeto sin tener que conocer su tipo intrínseco: esto es polimorfismo de subtipado. Permite no tomar en cuenta detalles de las clases especializadas de una familia de objetos, enmascarándolos con una interfaz común (siendo esta la clase básica).
Imagine un juego de ajedrez con los objetos reyreinaalfilcaballotorre y peón, cada uno heredando el objeto pieza.
El método 
movimiento podría, usando polimorfismo de subtipado, hacer el movimiento correspondiente de acuerdo a la clase objeto que se llama. Esto permite al programa realizar el movimiento.de_pieza sin tener que verse conectado con cada tipo de pieza en particular.




Sobrecarga

En programación orientada a objetos la sobrecarga se refiere a la posibilidad de tener dos o más funciones con el mismo nombre pero funcionalidad diferente. Es decir, dos o más funciones con el mismo nombre realizan acciones diferentes. El compilador usará una u otra dependiendo de los parámetros usados. A esto se llama también sobrecarga de funciones.
También existe la sobrecarga de operadores que al igual que con la sobrecarga de funciones se le da más de una implementación a un operador.
Sobrecarga es la capacidad de un lenguaje de programación, que permite nombrar con el mismo identificador diferentes variables u operaciones
El mismo método dentro de una clase permite hacer cosas distintas en función de los parámetros
Java no permite al programador implementar sus propios operadores sobrecargados, pero sí utilizar los predefinidos como el +. • C++, por el contrario si permite hacerlo.

Sobrecarga de métodos

Algunos métodos en una clase pueden tener el mismo nombre. Estos métodos deben contar con diferentesvvaloresvaloresalores argumentos. El compilador decide qué método invocar comparando los argumentos. Se generara un error si los métodos sólo varían en el tipo de retorno.


Ejemplo Articulo.java
public class Articulo {
private float precio;
public void setPrecio() {
precio = 3.50;
}
public void setPrecio(float nuevoPrecio) {
precio = nuevoPrecio;
}
}

Ej: Tenemos un método que soporta varios tipos de parámetros, entonces cuando hacemos uso de este, lo que hace el compilador es buscar el que posee ese tipo de parámetros
Color (int r, int g, int b)
Color (float a, float b, float c)
//--------------------------------------------
//r,g,b (son valores enteros entre 0 y 255)
//a,b,c (son valores flotantes entre 0.0 y 1.0)
Entonces cuando hacemos un llamado a este método (en este caso seria un constructor), el compilador hace referencia al tipo de parámetros. La sobrecarga seria redefinir cualquiera de estos métodos utilizando los mismos parámetros pero para un proceso distinto.