Actualizado el 21 de Marzo del 2018 (Publicado el 1 de Diciembre del 2017)
949 visualizaciones desde el 1 de Diciembre del 2017
518,5 KB
39 paginas
Creado hace 19a (19/12/2005)
Programación Orientada a Objetos
TEMA 5
Herencia Múltiple
Facultad de Informática
Universidad de Murcia
Índice
1.- Introducción
2.- Utilidades de la herencia múltiple
3.- Problemas con la herencia múltiple.
– Colisión de nombres
– Herencia repetida
• Conflicto cuando hay compartición
• Conflicto cuando hay replicación
4.- Herencia múltiple en Java: Interfaces
2
•1
1.- Introducción
• Las clases pueden necesitar mas de una clase padre
• Más difícil de usar e implementar que la herencia
simple.
• Algunos consideran que produce más inconvenientes
que ventajas. Según B. Meyer:
– “No puedo pensar en una aplicación seria escrita en Eiffel
que no use la herencia múltiple en un modo significativo”
– “Para discutir cuestiones conceptuales sobre H.M. es
necesario considerar el doble aspecto de la herencia:
subtipos y extensión modular”
3
Herencia múltiple y Extensión modular
MATH
R
STORABLE
R
S
S
• S es una especialización de R
• MATH incluye un paquete de rutinas matemáticas
• STORABLE ofrece servicios de persistencia de
objetos
4
•2
Herencia Múltiple y Subtipos
Ejemplo1: Implementación de los menús de una aplicación
i) Los menús son simples
MENU ARRAY [OPCION_MENU]
ii) Los menús contienen submenús
1) MENU TREE [OPCION_MENU]
“provocaría muchos cambios”
2)
{num_opciones
opciones, display}
MENU
OPCION_MENU
{menu, ejecutar}
SUBMENU
{ejecutar+//visualizar las opciones}
5
Ejemplo2: ”Profesores ayudantes están matriculados de
los cursos de doctorado”
PERSONAL_UNI
PROFESOR
ESTUDIANTE
PROFESOR_AYUDANTE
Ejemplo3: ”Añadir un nuevo tipo de cuenta que comparte a
la vez propiedades de cuenta de ahorro y
cuenta corriente”
CUENTA_BANCARIA
CUENTA_AHORRO CUENTA_CORRIENTE
6
•3
SOLUCIÓN:
Con herencia múltiple
Sin herencia múltiple
CUENTA_
BANCARIA
Perdemos:
• Polimorfismo
• Principio de Abierto-Cerrado
• Beneficios de la reutilización de la herencia
CUENTA_
BANCARIA
CUENTA_
AHORRO
CUENTA_
CORRIENTE
CUENTA_
AHORRO
CUENTA_
CORRIENTE
NUEVA_CUENTA
NUEVA_CUENTA
NUEVA_CUENTA
Debemos añadir a NUEVA_CUENTA
las propiedades de
CUENTA_CORRIENTE
7
Ejemplo4: ”Añadir a la jerarquía Smalltalkuna clase para
representar números complejos”
MAGNITUDE
{=, <, >, ..}
{+, -, *, / ..}
NUMBER
CHAR
INTEGER
Soluciones:
OPCION A
Magnitude
OPCION B
Magnitude
Number
Char
Number
Char
Integer
Complejo
Integer
Complejo
{=, >, <, ERROR}
8
•4
2.- Utilidades de la herencia múltiple
A) Combinar abstracciones de tipos (padres simétricos)
B)Matrimonio
de
implementación)
conveniencia
(Herencia
de
C) Herencia de estructura
D) Herencia de facilidades
9
A) Combinación de interfaces no relacionadas
Ejemplo1:
class WINDOW inherit
TREE [WINDOW]
RECTANGLE
feature
....
end
class TEXT_WINDOW inherit
WINDOW
STRING
feature
....
end
“Una ventana es un objeto
gráfico y un árbol de
ventanas”
“Una ventana de texto es
una ventana que manipula
texto”
10
•5
A) Combinación de interfaces no relacionadas
Ejemplo2:
class TREE [G] inherit
LIST [G]
LINKABLE [G]
feature
....
end
LIST permite obtener los hijos de un
nodo, añadir/eliminar un hijo,...
LINKABLE permite obtener el valor
de un nodo, su hermanos, su padre,
añadir un hermano...
“Un árbol es una lista, la lista
de sus hijos, pero también es
un elemento potencial de la
lista (un subárbol de otro
árbol)
“Un árbol es una lista que
es también un elemento de
la lista”
TREE[G] gráficamente
A
B
C
D
E
A
•
2
E
•
•
0
B
2
D
•
0
ARBOL es_un NODO
valor
siguiente
cabeza
numElementos
ARBOL es_una LISTA
C
•
•
0
11
12
•6
C) Herencia de Estructura:
Se desea que una clase posea ciertas propiedades además de
la abstracción que representa.
NUMERIC
COMPARABLE
DIAGRAMA
STORABLE
INTEGER
DIAGRAMA_CLASES
D) Herencia de Facilidades:
Existen clases que existen con el único propósito de ofrecer
unos servicios a sus descendientes
MATH
A
ASCII
A
ITERATOR
A
B
B
B
13
B) Matrimonio por conveniencia
Proporcionar una implementación para una abstracción definida
por una clase diferida usando las facilidades que proporciona
una clase efectiva
ARRAY [G]
PILA [G]*
LINKED_LIST [G]
export [NONE] all
export [NONE] all
PILA_FIJA [G]+
PILA_ENLAZADA [G]+
• La clase PILA_FIJA [G] sólo exporta las características exportadas por PILA [G]
y oculta las propiedades de ARRAY [G].
• La clase PILA_ENLAZADA [G] sólo exporta las características exportadas por
PILA [G] y oculta las propiedades de LINKED_LIST [G].
14
•7
B) Matrimonio por conveniencia
Proporcionar una implementación para una abstracción definida
por una clase diferida usando las facilidades que proporciona
una clase efectiva
ARRAY [G]
PILA [G]*
LINKED_LIST [G]
export [NONE] all
export [NONE] all
PILA_FIJA [G]+
PILA_ENLAZADA [G]+
HERENCIA DE IMPLEMENTACIÓN
• La clase PILA_FIJA [G] sólo exporta las características exportadas por PILA [G]
y oculta las propiedades de ARRAY [G].
• La clase PILA_ENLAZADA [G] sólo exporta las características exportadas por
PILA [G] y oculta las propiedades de LINKED_LIST [G].
15
s
y
a
r
r
a
o
d
n
a
s
u
s
a
2
/
1
l
i
P
e
d
n
ó
i
c
a
t
n
e
m
e
l
p
m
I
class PILA_FIJA [G] inherit
PILA [G]
ARRAY [G] export {NONE} all
rename
end
creation make
feature
put as array_put, make as make_array,
count as capacity
count: INTEGER; --hace efectiva como atributo una
--característica diferida
make (n: INTEGER) is
require tamaño_no_negativo: n>=0;
do
array_make (1,n)
ensure
capacidad: capacity = n;
vacia: count = 0
end
16
•8
s
y
a
r
r
a
o
d
n
a
s
u
s
a
2
/
2
l
i
P
e
d
n
ó
i
c
a
t
n
e
m
e
l
p
m
I
full: BOOLEAN is do
--¿Está llena la representación de la pila?
Result:= (count = capacity)
end;
put (x: G) is
-- Pone x en la cima de la pila
require not full
do
count:= count + 1;
array_put (x, count)
end;
invariant
count>=0 ;
count <= capacity
...
end -- PILA_FIJA [G]
Problema en ejecución
Sea la declaración
entonces
p: PILA_FIJA [INTEGER]
p.array_put (32,45)
provocaría error en tiempo de compilación.
¿Provocaría error el siguiente código?
p: PILA_FIJA [INTEGER]; a: ARRAY [INTEGER]
...
a:= p
a.put (32,45)
{se ejecuta la rutina put de array}
17
18
•9
Herencia de implementación
ARRAY [G]
PILA [G]*
Result:= (count = capacity)
PILA_FIJA [G]+
full: BOOLEAN is do
end;
put (x: G) is do
count:= count + 1;
array_put (x, count)
end;
19
¿Cómo se haría sin herencia de implementación?
PILA [G]*
ARRAY [G]
imp
(cid:47) Penalización rendimiento
(cid:47) Tedioso uso prefijos
Result:= (count = imp.capacity)
Result:= (count = capacity)
PILA_FIJA [G]+
full: BOOLEAN is do
full: BOOLEAN is do
end;
end;
put (x: G) is do
put (x: G) is do
count:= count + 1;
count:= count + 1;
imp.put (x, count)
array_put (x, count)
end;
end;
Toda manipulación de la representación requiere una llamada a una
característica de ARRAY con imp como receptor.
20
•10
Clientela vs. Herencia de implementación
• “B hereda de A” es una decisión de diseño más comprometedora
que “B es cliente de A”.
• Si “B es cliente de A” podemos cambiar la implementación de A
sin afectar a B.
¿Cuándo es apropiada una herencia de implementación?
• “Cuando la elección de la implementación es una parte esencial del
diseño de la clase, y no va a cambiar, como en PILA_FIJA [G]”
• En ese caso ofrece una solución más simple, eficiente y legible.
C++ y Herencia de implementación
A
{f,g}
C
B
C* oc; A* oa; B* ob
oa = ob
{ERROR}
ob.f( ) {ERROR}
class A {
public:
void f ( );
void g ();
protected:...
private:...}
class B: private A {
public: ...
protected:...
private:...}
21
22
•11
Ocultar las propiedades del padre
• Eiffel:
– export {NONE}
– class Pila inherit Array export {NONE} ALL
• C++:
– herencia privada
– class Pila: private Array{...};
• Java:
– throw new UnsupportedOperationException();
– invocar con super a las propiedades del padre
– class Pila extends Array{
throw new UnsupportedOperationException();
public void add(int pos, Object valor) {
}
public void push(Object valor){
}
super.add(tope,valor);
}
23
Ejemplo: Figuras Compuestas
Vamos a ver un patrón de diseño general (de utilidad en
muchas áreas) que describe estructuras compuestas a través
de la herencia múltiple, usando una clase contenedora (lista)
como una de sus clases padre, PATRÓN COMPOSITE.
class FIGURA_COMPUESTA inherit
FIGURA
LINKED_LIST [FIGURA]
feature
…
end
“Una figura compuesta es una figura”
“Una figura compuesta es una lista de figuras”
24
•12
Figura Compuesta con herencia múltiple
FIGURA*
visualizar
girar
…
LISTA[FIGURA]
start
after
forth
FIGURA_COMPUESTA
visualizar
girar
…
visualizar is do
girar(…) is do
from start until after
from start until after
loop
loop
item.visualizar
item.girar(…)
forth
forth
end
end
end
end
“Muchas rutinas con esta estructura” (rotar, trasladar, …)
25
Patrón Composite: Herencia simple
Componente
operacion
Simple
operacion
Compuesto
operacion
componentes
for (int i=0; i<componentes.length();++i)
componentes[i].operacion();
26
•13
Figura Compuesta con Herencia simple
Figura
dibujar
Poligono
dibujar
FiguraCompuesta
dibujar
vs Herencia múltiple
componentes: LINKED_LIST[FIGURA]
dibujar is do
from componentes.start
until componentes.after
loop
componentes.item.dibujar
componentes.forth
end
end
27
Solución: Figuras Compuestas e Iteradores
coleccion:LINEAR_LIST[G]
forEach+
action*
...
LINEAR_ITERATOR*
redefine coleccion
coleccion
FIGURA_COMPUESTA_ITERATOR*
action +
VISUALIZAR_ITERATOR
action (f: FIGURA) is do
f.visualizar
end
action +
...
ROTAR_ITERATOR
action (f: FIGURA) is do
f.rotar
end
28
•14
FIGURA_COMPUESTA
visualizar is
rotar is
local
local
iv: VISUALIZAR_ITERATOR
ir: ROTAR_ITERATOR
do
do
end
end
!!iv.make(Current)
!!ir.make(Current)
iv.forEach
ir.forEach
S
E
R
O
D
Comentarios de: TEMA 5 Herencia Múltiple (0)
No hay comentarios