miércoles, 2 de abril de 2008

Reutilización del código y relaciones entre clases

“Reutilización de código” no se refiere a copiar (ctrl+c) y pegar (ctrl+v)

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 echo 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 cuando 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 esta 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.

Herencia:
En java aunque no establezcamos de manera explicita la herencia siempre está presente, ya que todas las clases que creemos heredan de la clase Object, por eso es valido decir que en java todo es un objeto. La sintaxis para la composición 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 código dando el nombre de la clase como siempre pero, antes de la apertura del límite cuerpo de clase, pondremos la palabra clave "extends" seguida por el nombre de la clase base. Cuando hagamos esto, obtendremos automáticamente todos los datos miembros y métodos 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 código de UnidadDeTiempo lo tememos disponible en la clase Horas, pero que partes tenemos disponibles?, todos los atributos y los métodos de la clase padre están disponibles en la clase hija pero dependiendo de los modificadores de acceso o visibilidad de estos, por ejemplo los atributos y métodos de tipo friendly solo estarán disponibles para las clases hijas que heredan de una clase padre en el mismo paquete, los atributos y métodos de tipo public estarán 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 también son accesibles desde las clases hijas.

El código de nuestra clases hijas no tienen porque limitarse solo al código heredado, de hecho casi siempre la herencia se hace para extender la funcionalidad de las clases heredadas añadiendo nuevos métodos y atributos.

La composición y la herencia:
Tanto la composición como la herencia permiten poner sub-objetos dentro de tu nueva clase. Podríamos preguntarnos cuál es la diferencia entre los dos, y cuándo elegir uno en lugar del otro. La composición es generalmente usada cuando deseamos las características de una clase existente dentro de una nueva clase, pero no su interfaz. Es decir, ponemos un para poder usarlo para implementar características 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 implementación ocultándose 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 más fácil de entender.

Cuando heredamos, estamos cogiendo una clase existente y creando una versión especial de esa clase. En general, esto significa que estamos tomando una clase de propósito general, especializándola para un caso o necesidad particular. Pensando un poco, podrá entender que no tendría sentido construir un coche usando un objeto vehículo (un coche no contiene un vehículo, ¡es un vehículo!). La relación es- un viene expresada por la herencia, y la relación tiene un viene expresada por la composición.

15 comentarios:

Anónimo dijo...

Hola, he leido su entrada acerca de la reutilizacion de codigo porque necesito una solucion a un problema que me ha surgido, a ver si tuviera un poco de tiempo para resolvermela, si fuera tan amable.
Tengo que "reutilizar" el codigo de un algoritmo ya implementado (FP-Growth) en una clase Java; este algoritmo está en C y me han dicho que no necesito traducirlo. Como debo hacerlo? Muchas gracias

alejo dijo...

para ese tipo de uso de codigos ya creados, verifca el manejo de metodos nativos en java

Silvani dijo...

Muy bien, me sirvio, chido.

Anónimo dijo...

MUchas Gracias

PâµL.exe dijo...

OIe muxas graciaz x el posteo.. me ayudo mucho a entender este tema... lamentablemente mi profesor no lo sabe explicar mejor q tu!!! xD ajjaja nuevament muxAz gRaciaz!!...

harbin dijo...

Hola soy estudiante de ingenieria de sistemas del 3 ciclo en la universida Santo Toribio de Mogrovejo estoy llevando todo lo que es programacion orientada a objetos ... Su articulo es muy importante me gustaria profundizar mi aprendizaje en lo que es programacion Orientada a objetos le dejo mi msn the_bigharby@hotmail.com

alejo dijo...

Harbin, que dudas tiene, a ver si lo puedo ayudar y publicar entradas sobre estas dudas y estas contribuyen a que todos aprendamos un poco mas

sigifredo89 dijo...

http://desarrolladores-poo.blogspot.com/

Anónimo dijo...

hola, quisiera saber si ud no tiene o no publicarà entradas pero con lenguaje C++
att.vanessa

alejo dijo...

Vanessa, que entradas te gustaría trabajar en C++ para ayudarte a solucionar tus dudas.

Anónimo dijo...

muy bueno el contenido me sirvio de mucho

juan tovar dijo...

hey... exelente ejemplo, me quedó bastante claro... gracias

Anónimo dijo...

que pena a este codigo q le hace falta?¿

Anónimo dijo...

¿Me puedes decir dónde encuentro la librería, co.edu.udistrital.prycalculadora.logica, dado que me da error?

Muchas Gracias.

ajsalinasmx@hotmail.com

Unknown dijo...

Hola buenos días desde México, tengo una duda en relación de querer reutilizar el código y poder realizar una cuenta atras como sería la lógica de esto:

public int forward(){
if(valor == tope)
valor=0;
else
valor++;
return valor;
}

Y de esto otro

public String avanzar(){
seg = s.forward();
if(seg==0){
min=m.forward();
if(min==0){
hor=h.forward();
}
}
cadena = hor + " : " + min + " : " + seg;
return cadena;
}