4.1 Definición de 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.

 

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"

 

4,2 Clases Abstractas

 

Hay ocasiones, cuando se desarrolla una jerarquía de clases en que algún 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 geométricas. Podríamos pensar en tener una clase genérica, que podría llamarse Figura Geométrica y una serie de clases que extienden a la anterior que podrían ser Círculo, Polígono, etc. Podría haber un método dibujar dado que sobre todas las figuras puede llevarse a cabo esta acción, pero las operaciones concretas para llevarla a cabo dependen del tipo de figura en concreto (de su clase). Por otra parte la acción dibujar no tiene sentido para la clase genérica Figura Geométrica, porque esta clase representa una abstracción del conjunto de figuras posibles.

Para resolver esta problemática Java proporciona las clases y métodos abstractos. Un método abstracto es un método declarado en una clase para el cual esa clase no proporciona la implementación (el código). Una clase abstracta es una clase que tiene al menos un método abstracto. Una clase que extiende a una clase abstracta debe implementar los métodos abstractos (escribir el código) o bien volverlos a declarar como abstractos, con lo que ella misma se convierte también en clase abstracta.


Declaración e implementación de métodos 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 declaración. Los métodos abstractos se declaran también con el mismo modificador, declarando el método pero sin implementarlo (sin el bloque de código encerrado entre {}). La clase derivada se declara e implementa de forma normal, como cualquier otra. Sin embargo si no declara e implementa los métodos abstractos de la clase base (en el ejemplo el método dibujar) el compilador genera un error indicando que no se han implementado todos los métodos 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 ningún 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 implementación y encaja bien con la idea de que algo abstracto no puede materializarse.

La característica de hacer una Clase/Método abstract reside en que no puede ser generada una instancia de la misma, este comportamiento se demuestra en el método principal (main)

 Aunque dentro del método sea generado un Arreglo de esta Clase abstracta, recuerde que un arreglo es únicamente un contenedor de Objetos, esto permite que sea generado sin ningún error.

 Dentro de comentarios se encuentra la generación de una instancia del tipo Instrumento la cual generaría un error al ser compilada la Clase.

 

 

 

 

 

 

4.3 Definición, implementación y herencia de interfaces

 

INTERFACES

Introducción

Las interfaces Java son expresiones puras de diseño. Se trata de auténticas conceptualizaciones no implementadas que sirven de guía para definir un determinado concepto (clase) y lo que debe hacer, pero sin desarrollar un mecanismo de solución.

Se trata de declarar métodos abstractos y constantes que posteriormente puedan ser implementados de diferentes maneras según las necesidades de un programa.

Por ejemplo una misma interfaz podría ser implementada en una versión de prueba de manera poco óptima, y ser acelerada convenientemente en la versión definitiva tras conocer más a fondo el problema.

 

Declaración

Para declarar una interfaz se utiliza la sentencia interface, de la misma manera que se usa la sentencia class:

interface MiInterfaz {

int CONSTANTE = 100;

int metodoAbstracto( int parametro );

}

Se observa en la declaración que las variables adoptan la declaración en mayúsculas, pues en realidad actuarán como constantes final. En ningún caso estas variables actuarán como variables de instancia.

Por su parte, los métodos tras su declaración presentan un punto y coma, en lugar de su cuerpo entre llaves. Son métodos abstractos, por tanto, métodos sin implementación

 

Implementación de una interfaz

Como ya se ha visto, las interfaces carecen de funcionalidad por no estar implementados sus métodos, por lo que se necesita algún mecanismo para dar cuerpo a sus métodos.

La palabra reservada implements utilizada en la declaración de una clase indica que la clase implementa la interfaz, es decir, que asume las constantes de la interfaz, y codifica sus métodos.

Un interfaz puede heredar de varios interfaces sin ningún problema. Sin embargo, una clase solamente puede heredar de una clase base, pero puede implementar varios interfaces. También, el JDK ofrece la posibilidad de definir un interfaz vacío, como es el caso de Serialize, que permite serializar un objeto. Un interfaz vacío se puede utilizar como un flag, un marcador para marcar a una clase con una propiedad determinada.

La aplicación java514.java, ilustra algunos de los conceptos referentes a los interfaces. Se definen dos interfaces, en uno de ellos se definen dos constantes y en el otro se declara un método put() y un método get(). Las constantes y los métodos se podrían haber colocado en la misma definición del interfaz, pero se han separado para mostrar que una clase simple puede implementar dos o más interfaces utilizando el separador coma (,) en la lista de interfaces.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

4.4 Definición, uso y aplicaciones de las variables polimórficas

 

Variables polimórficas

En Java, las variables que contienen objetos son variables polimórficas. El término «polimórfico» (literalmente: muchas formas) se refiere al hecho de que una misma variable puede contener objetos de diferentes tipos (del tipo declarado o de cualquier subtipo del tipo declarado). El polimorfismo aparece en los lenguajes orientados a objetos en numerosos contextos, las variables polimórficas constituyen justamente un primer ejemplo.

Observemos la manera en que el uso de una variable polimórfica nos ayuda a simplificar nuestro método listar. El cuerpo de este método es

 

for (Elemento elemento : elementos)

elemento.imprimir();

 

En este método recorremos la lista de elementos (contenida en un ArrayList mediante la variable elementos), tomamos cada elemento de la lista y luego invocamos su método imprimir. Observe que los elementos que tomamos de la lista son de tipo CD o DVD pero no son de tipo Elemento. Sin embargo, podemos asignarlos a la variable elemento (declarada de tipo Elemento) porque son variables polimórficas. La variable elemento es capaz de contener tanto objetos CD como objetos DVD porque estos son subtipos de Elemento.

 

Enmascaramiento de tipos (Casting)

Algunas veces, la regla de que no puede asignarse un supertipo a un subtipo es más restrictiva de lo necesario. Si sabemos que la variable de un cierto supertipo contiene un objeto de un subtipo, podría realmente permitirse la asignación. Por ejemplo:

 

Vehiculo v;

Coche a = new Coche();

v = a; // Sin problemas

a = v; // Error, según el compilador

Obtendremos un error de compilación en a = v.

 

El compilador no acepta esta asignación porque como a (Coche) tiene mas atributos que v (Vehículo) partes del objeto a quedan sin asignación. El compilador no sabe que v ha sido anteriormente asignado por un coche.

Podemos resolver este problema diciendo explícitamente al sistema, que la variable v contiene un objeto Coche, y lo hacemos utilizando el operador de enmascaramiento de tipos, en una operación también conocida como casting.

a = (Coche)v; // correcto

En tiempo de ejecución, el Java verificará si realmente v es un Coche. Si fuimos cuidadosos, todo estará bien; si el objeto almacenado en v es de otro tipo, el sistema indicará un error en tiempo de ejecución (denominado ClassCastException) y el programa se detendrá.

 

           

4.5 Reutilización del código

 

Lo primero que se les viene a la cabeza a los estudiantes (y a muchos profesionales) cuando se les menciona la reutilización del código es el famoso copiar y pegar al que se han acostumbrado en la programación estructurada, y de hecho muchos lo hacen en poo, lo cual es una de las practicas que más encarece el desarrollo de software. Como todo en Java, el problema se resuelve con las clases. Para reutilizar el código 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 código existente.

Una forma de hacer esto es crear objetos de nuestras clases existentes dentro de la nueva clase. Esto se conoce como composición porque la nueva clase está compuesta de objetos de clases existentes. Estamos reutilizando la funcionalidad del código, 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 añadimos código 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.


Composición:
Hasta ahora hemos usado la composición de cierta manera, ej. cuando hacemos una interfaz gráfica de usuario, nuestra clase de interfaz gráfica esta compuesta por un frame, unos panel, botones, etc. todos estos objetos componen el objeto de interfaz gráfica. Es decir que la composición consiste en poner manejadores de objetos dentro de nuestra clase, estos manejadores de objetos no serán otra cosa que instancias de las clases en las que nos estamos basando para crear la nueva clase.

Recordemos que la forma para determinar cuándo usar composición es cuando podemos decir que nuestra nueva clase “tiene un” elemento de otro tipo de objetos, por ejemplo un cronómetro 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 través del constructor de nuestra clase creamos las instancias de cada una de ellas.

By:JOSE ANTONIO RAMÓN LEON
PROGRAMACION ORIENTADA A OBJETOS
ITZO
CREADO: MARTES 5 DE JUNIO DEL 2012
ORIENTADOR: VICENTE DE LA CRUZ MUÑÓZ
Hoy habia 2 visitantes (4 clics a subpáginas) ¡Aqui en esta página!
Este sitio web fue creado de forma gratuita con PaginaWebGratis.es. ¿Quieres también tu sitio web propio?
Registrarse gratis