Documentos de Académico
Documentos de Profesional
Documentos de Cultura
ISSN 1668-7523
RESUMEN
En el artculo se comentan algunos aspectos de la utilizacin de relaciones de herencia mltiple, para el
desarrollo de software orientado a objetos. En particular se analiza una alternativa de implementacin de
este tipo de relaciones en el lenguaje Java. Dado que el mismo no permite implementar relaciones de
herencia mltiple en forma directa, las mismas se "simulan" mediante la utilizacin de interfaces, lo cual
se muestra a travs de un ejemplo, en el cual se discuten algunos aspectos de la implementacin. Tambin
se analiza el modo de soportar caractersticas como reusabilidad, polimorfismo, redefinicin de mtodos y
definiciones de mtodos forwarding, y se comentan algunas de las desventajas que presenta.
PALABRAS CLAVE
Herencia Mltiple. Lenguaje Java. Programacin Orientada a Objetos. Patrones.
11
Proyecto Leonardo
ISSN 1668-7523
INTRODUCCIN
Uno de los objetivos de la programacin orientada a objetos, es incrementar la
productividad en el desarrollo de software. Uno de los modos de lograr sto, es
mediante la reutilizacin de cdigo existente, para lo cual las relaciones de herencia son
uno de los medios ms utilizados.
Un buen diseo del esquema de relaciones de herencia resulta crtico, ya que si el
mismo est bien hecho facilitar la reutilizacin de cdigo, permitiendo mantener al
mismo tiempo el control del desarrollo del software. Por otra parte, un mal diseo, har
que la reutilizacin de cdigo se vea dificultada o impedida.
El diseo del lenguaje Java, imposibilita pensar el diseo de un programa aplicando
herencia mltiple (Eckel, 2000), como se podra hacer por ejemplo en C++. Java
permite nicamente una forma cercana al concepto de herencia mltiple, a travs de la
implementacin de interfaces. Esta restriccin de los diseadores del lenguaje, les ha
permitido simplificar la implementacin del compilador.
Cuando se utilizan lenguajes como C++, frecuentemente se hace un uso indebido de las
relaciones de herencia mltiple, lo cual hace que el mismo pierda integridad. En Java
esto no ocurre, ya que no ofrece soporte para este tipo de relaciones.
Si bien las relaciones de herencia mltiple, aparecen muy pocas veces frente a las de
herencia simple, ambos esquemas tienen ventajas y desventajas (Ghan Bir Singh, 1995);
en ocasiones se presentan situaciones en las cuales la utilizacin de relaciones de
herencia mltiple resulta conveniente.
HERENCIA MLTIPLE
Dentro de los lenguajes O.O. (orientados a objetos) existen algunos que soportan
herencia mltiple, como C++ (Stroustrup, 2000) y Eiffel (Meyer, 2001); en cambio
otros no, como en el caso de Smalltalk y Java. Si bien, la mayora de las situaciones
pueden resolverse sin recurrir a herencia mltiple, en algunos casos es conveniente
contar con esta caracterstica, a fin de lograr una mejor implementacin de la aplicacin.
Desde el punto de vista del diseo de un lenguaje, soportar herencia mltiple complica
la tarea de implementacin, ya que hay que prever cmo resolver situaciones como la
que se muestra en la Figura 1, mediante el diagrama UML de relaciones de herencia
mltiple entre las clases A, B y C (Fowler y Scott 2000). Cuando un objeto de clase C
tiene que acceder al atributo p, el lenguaje debe tener algn medio de discriminar a cul
atributo p se quiere referir, si al de la clase A o la B.
Proyecto Leonardo
ISSN 1668-7523
13
Proyecto Leonardo
ISSN 1668-7523
HERENCIA EN JAVA
En vista de las situaciones de herencia mltiple descriptas anteriormente que se pueden
presentar, parece razonable que el diseador de un lenguaje prefiera no tener que
implementar dicho mecanismo. Pero en el caso de Java, tambin existe un motivo que
va ms all de la conveniencia para el implementador del lenguaje. La ejecucin de un
programa Java se basa en un intrprete de un seudocdigo de mquina (byte-code). Esta
caracterstica es lo que ha permitido la independencia de la plataforma sobre la que se
ejecuta una aplicacin Java.
El uso de bibliotecas de clases en Java es un mecanismo muy flexible, dado que la
mayora de los enlaces se resuelven durante el tiempo de ejecucin. As, se puede
recompilar una clase, sin necesidad de hacer lo mismo con su subclase, y la aplicacin
va a continuar ejecutndose en forma correcta. Esta caracterstica podra dar lugar a
errores, en el caso de que existiera herencia mltiple. En el ejemplo de la Figura 1, si
suponemos que en A agregamos un mtodo cuya cabecera coincide con la de un mtodo
ya definido en B, y si desde C se activa el mtodo, ahora no alcanza con recompilar A,
sino que ser necesario resolver la ambigedad en la activacin del mtodo desde C y
recompilar tambin esta ltima clase.
14
Proyecto Leonardo
ISSN 1668-7523
15
Proyecto Leonardo
ISSN 1668-7523
16
Proyecto Leonardo
ISSN 1668-7523
17
Proyecto Leonardo
ISSN 1668-7523
Proyecto Leonardo
ISSN 1668-7523
Implementacin de forwarding
Supongamos que el cdigo de las clases C y D, ha sido modificado como se muestra a
continuacin, donde aparece un mtodo denominado nuevo(), que es implementado en
la clase C y luego es redefinido en D.
class C extends A {
public void algo() {
System.out.println("C");
super.algo();
}
public void otro() {
System.out.println("Otro");
nuevo();
}
public void nuevo() {
System.out.println("C: nuevo");
19
Proyecto Leonardo
ISSN 1668-7523
}
}
class D extends C implements iB {
private iB objBase = new B();
public void algo() {
System.out.println("D");
objBase.hace();
super.otro();
}
public void hace() {
objBase.hace();
}
public void nuevo() {
System.out.println("D: nuevo");
}
}
Listado 3: Implementacin de forwarding
Para los siguientes enunciados, cuando se procese la llamada incluida en otro() de C, la
implementacin del mtodo nuevo() que se activar ser la correspondiente a la clase D
y no a C. Este comportamiento se debe a que el objeto que inici la secuencia de
activaciones de mtodos pertenece a la clase D, y lo que se hace es activar un mtodo
que se encuentra definido ms adelante (forwarding) en la jerarqua de herencia.
C obj = new D();
obj.algo();
En el caso de plantearse una situacin semejante para la clase B, se debe simular el
mismo comportamiento. Esto se puede hacer manteniendo una referencia inversa desde
el objeto base de la clase B al objeto derivado del tipo D. Entonces del cdigo de
ambas clases, para una situacin similar a la antes descripta sera el siguiente, con lo
cual se completa el esquema presentado en la Figura 5.
interface iB {
public void algo();
public void hace();
public void nuevo();
}
class B extends A implements iB {
private iB objDeriv;
public B() {
super();
objDeriv = this;
}
public B(D obj) {
super();
objDeriv = obj;
}
public void algo() {
super.algo();
20
Proyecto Leonardo
ISSN 1668-7523
System.out.println("B");
}
public void hace() {
System.out.println("Hace");
objDeriv.nuevo();
}
public void nuevo() {
System.out.println("B: tres");
}
}
class D extends C implements iB {
private iB objBase;
public D() {
super();
objBase = new B(this);
}
public void algo() {
objBase.hace();
super.otro();
System.out.println("D");
}
public void hace() {
objBase.hace();
}
public void nuevo() {
System.out.println("D: tres");
}
}
Listado 4: Implementacin final del esquema de la Figura 5
Las referencias cruzadas se implementan, agregando el atributo objDeriv en B, que
debe ser del tipo iB porque se necesitar referenciar con esta variable objetos del tipo B
o D. Adems se han incorporando dos constructores, que establecen los vnculos en el
momento de crear un objeto D. El constructor sin parmetros en B, se requiere por
haber sobrecargado los constructores de la clase, pero adems se necesita para
inicializar el atributo objDeriv con la referencia a s mismo, cuando la creacin de un
objeto B no es consecuencia de la creacin de un objeto de la clase D. El mtodo
nuevo() adems de en las clases, debe ser declarado en la interface.
La activacin del mtodo nuevo() en B, se hace utilizando la variable objDeriv, que
referencia un objeto B o D, segn corresponda.
Reutilizacin
Si se quiere crear una clase que herede de D, reutilizando mtodos definidos en la
jerarqua de herencia, la tarea no resulta complicada.
Por ejemplo una clase X que hereda de D, en la cual se redefinen los mtodos algo() y
nuevo(). Tambin se define un mtodo propio(), que reutiliza los mtodos hace() y
otro(), de las clases B y C respectivamente.
21
Proyecto Leonardo
ISSN 1668-7523
class X extends D {
public void propio(){
System.out.println("Propio");
hace();
otro();
}
public void algo() {
propio();
}
public void nuevo() {
System.out.println("X: nuevo");
}
}
A continuacin se declara una variable del tipo A, que por ser la raz de la jerarqua
de herencia, posibilita referenciar objetos pertenecientes a cualquiera de las subclases.
Luego se crea un objeto del tipo X y se activa el mtodo algo().
A p = new X();
p.algo();
En este caso la salida es la siguiente:
Propio
Hace
X: nuevo
// Salida de la llamada a nuevo(), desde hace() en B
Otro
X: nuevo
Como se puede observar los comportamientos del programa, debidos a la aplicacin de
conceptos como reutilizacin, polimorfismo y forwarding, son los que cabe esperar.
CONCLUSIONES
Se ha analizado una alternativa de implementacin de herencia mltiple, en un lenguaje
como Java, que no soporta este tipo de relaciones. Para esto se utiliza una interface,
cuya funcin es proveer el acceso a la clase de la cual se pretende heredar en forma
mltiple. Varios aspectos del tema abordado, se enmarcan dentro de lo que se denomina
patrones de diseo, donde aparecen patrones como agente, agente virtual, interfaz de
negocios.
A fin de ilustrar las modificaciones que se deben realizar sobre el modelo original, para
simular herencia mltiple, se ha utilizado el nombre iB para la interface. Sin embargo,
en una situacin de aplicacin del esquema propuesto, se debera denominar a la clase
B, por ejemplo como implB (implementacin de B) y a la interface iB con el nombre B,
a fin de mantener la coherencia en los nombres de identificadores del modelo original.
Si bien la implementacin requiere de varios artificios de codificacin, la complejidad
de esta queda oculta para quien reutiliza la clase D, por lo tanto su tarea no se ve
complicada, obteniendo como resultado el comportamiento esperable, de un lenguaje
que soporte esquemas de herencia mltiple.
22
Proyecto Leonardo
ISSN 1668-7523
REFERENCIAS
Booch, G. (1994). Object Oriented Analysis and Design: With Applications. Addisson
Wesley
Budd, T. (2002). Introduction to Object-Oriented Programming, 3/E. Addison-Wesley
Cardelli, L. Wegner, P. (1985). On Understanding Types, Data Abstractions, and
Polymorphism. Computing Surveys. 17.4: 471-523
Cornell, G. Horstmann, C. S. (1996). Core Java. The Sun Press. Prentice Hall
Eckel, B. (2000). Thinking in Java. Prentice Hall.
Fowler, M. Scott, K. (2000). UML Distilled: A Brief Guide to the Standard Object
Modeling Language 2/E. Addisson Wesley
Gamma, E. Helm, R. Johnson, R. Vlissides, J. (1995). Design Patterns: Elements of
Reusable Object-Oriented Software. Addisson Wesley
Ghan Bir Singh. (1995). Rensselaer Polytechnic Institute at HGC. Single Versus
Multiple Inheritance in Object Oriented Programming. Hartford, CT, USA
Meyer, B. (2001). An Eiffel Tutorial, ISE Technical Report TR-EI-66/TU. Interactive
Software Engineering Inc.
Seidewitz, E. (1996). Controlling Inheritance. Journal of Object Oriented Programming.
8.8: 36-42
Stroustrup, B. (2000). The C++ Programming Language. Addisson Wesley
23