Title: Herencia
1Herencia
Ingeniería del Software
TEMA 3
Jesús García Molina Facultad de
Informática Universidad de Murcia http//dis.um.es
/jmolina/
2Contenidos
- Introducción
- Herencia y Sistema de tipos
- Polimorfismo y Ligadura dinámica
- Genericidad y Herencia
- Intento de asignación
- Clases Diferidas
- Herencia y Ocultación de Información
- Herencia y Asertos
- Herencia y Creación
- Herencia Múltiple
- Interfaces Java
- Iteradores
- Herencia Repetida
- Implementación de la ligadura dinámica
- Categorías de herencia
- Heurísticas
3Introducción
- Las clases no son suficientes para conseguir los
objetivos de reutilización y extensibilidad. - Necesidad de mecanismos para generar código
genérico - Capturar aspectos comunes en grupos de
estructuras similares - Independencia de la representación
- Variación en estructuras de datos y algoritmos
- Necesidad de mecanismos para favorecer
- Principio Abierto-Cerrado y Principio Elección
Unica - Estructuras de datos polimórficas.
4Código genérico
- // en ColeccionSecuencialG
- buscar (v G)Boolean is do
- from inicio
- until final or encontrado(v)
- loop
- avanzar
- end
- Result not final
- end
Qué necesitamos?
- Clases Genéricas
- Polimorfismo
- Ligadura dinámica
- Clases abstractas
5Introducción
- Entre algunas clases pueden existir relaciones
- Especialización, Extensión, Combinación
- Libros y Revistas son tipos de publicaciones
- Un rectángulo es una especialización de
polígono - Una pila puede definirse a partir de una cola o
viceversa - Una ventana de texto es un rectángulo dónde se
manipula texto
Tiene sentido crear una clase a partir de otra?
Herencia permite registrar y usar estas relaciones
6Introducción
- Necesitamos un mecanismo que posibilite la
definición de una nueva clase a partir de otra
existente - HERENCIA
- La herencia organiza las clases en una estructura
jerárquica - JERARQUIAS DE CLASES
- No es solo un mecanismo para compartir código.
- Consistente con el sistema de tipos del lenguaje
7Jerarquías de clases Ejemplos
PUBLICACION
LIBRO
REVISTA
MAGAZINE
INVESTIGACION
LIBRO_TEXTO
FIGURA
POLIGONO
CIRCULO
RECTANGULO
8Introducción
Si B hereda de A entonces B incorpora la
estructura (atributos) y comportamiento (métodos)
de la clase A, pero puede incluir
adaptaciones - B puede añadir nuevos
atributos - B puede añadir nuevos métodos - B
puede redefinir métodos - B puede renombrar
atributos o métodos - B puede implementar un
método diferido en A Adaptaciones
dependientes del lenguaje
9Redefinición de métodos
- Adaptación disponible en cualquier lenguaje OO.
- Debe mantenerse la semántica.
- Dos usos principales
- Refinamiento Extender el método original
- Reemplazo Mejorar la implementación
fA
redefine f
fB
10Redefinición de métodos
LISTA G
insertar (vG)
abrir
VENTANA
redefine insertar
redefine abrir
LISTA_ORDENADA G
VENTANA_CON_BORDE
insertar (vG)
abrir
11Clase Raíz
- Puede existir una clase raíz en la jerarquía de
la cual heredan las demás directa o
indirectamente. - Incluye todas las características comunes a todas
las clases - Eiffel clase ANY
- Smalltalk clase Object
- Java clase Object
- C no existe
12Tipos de herencia
A
- Herencia simple
- Una clase puede heredar de una única clase.
- Ejemplos Smalltalk, Java
- Herencia múltiple
- Una clase puede heredar de varias clases.
- Clases forman un grafo dirigido aciclíco
- Ejemplos Eiffel, C
C
B
E
D
B
C
A
13Terminología
- B hereda de A
- B es descendiente de A (Eiffel)
- A es un ascendiente de B (Eiffel)
- B es subclase de A (Smalltalk,
Java) - A es superclase de B (Smalltalk,
Java) - B es una clase derivada de A (C)
- A es la clase base de B (C)
14El proceso de heredar es transitivo
A
- B hereda de A
- C hereda de B y A
- B y C son descendientes (subclases) de A
- B es un descendiente directo de A
- C es un descendiente indirecto de A
B
C
15Terminología
- Descendiente propio de una clase
- Todas las clases que heredan de ella directa o
indirectamente - Ej. B, C, D E y F son descendientes propios de A
- Descendiente de una clase
- La clase y todos sus descendientes propios
- Ej. Los descendientes de A incluyen a A
16Cómo detectar la herencia?
- Generalización (Factorización)
- Se detectan clases con un comportamiento común
(p.e. Libro y Revista en Publicación ) - Especialización (Abstracción)
- Se detecta que una clase es un caso especial de
otra (p.e. Rectangulo de Poligono)
No hay receta mágica para crear buenas
jerarquías Pueden existir diversos criterios
Problemas con la evolución de la jerarquía
17Ejemplo Polígonos y Rectángulos
- Tenemos la clase POLIGONO y necesitamos
representar rectángulos
Debemos crear la clase RECTANGULO partiendo de
cero?
Entre polígonos y rectángulos existen similitudes
y diferencias
18- class POLIGONO creation ...
- feature
- vertices LINKED_LIST PUNTO
- feature
- numero_vertices INTEGER
- rotar (centroPUNTO anguloREAL) is do .. end
- trasladar (a, b REAL) is do .. end
- visualizar is do .. end
- perimetro REAL is do .. end
-
- invariant
- numero_vertices vertices.count
- número_vertices gt3
- end -- class POLIGONO
19- trasladar (a, b REAL) is do
- from vertices.start
- until vertices. after
- loop
- vertices.item.trasladar(a,b)
- vertices.forth
- end
- end
-
- rotar (centro, angulo REAL) is do
- from vertices.start
- until vertices. after
- loop
- vertices.item.rotar(centro,angulo)
- vertices.forth
- end
- end
20- perimetro REAL IS
- local actual, anterior PUNTO
- do
- from vertices.start actual
vertices.item - until vertices.is_last
- loop
- anterior actual
- vertices.forth
- actual vertices.item
- Result Result actual.distancia(anterior)
- end
- Result Result actual.distancia(vertices.fi
rst) - end
21Clase RECTANGULO
- Un rectángulo tiene muchas de las características
de un polígono (rotar, trasladar, vértices,..) - Pero tiene características especiales (diagonal)
y propiedades especiales (4 lados, ángulos
rectos) - Algunas características de polígono pueden
implementarse más eficientemente - Rectangulo hereda de Poligono
22Clase RECTANGULO
- class RECTANGULO inherit POLIGONO
- redefine perimetro
- creation crear
- feature
- lado1, lado2 REAL
- diagonal REAL
- crear (centroPunto s1, s2, anguloreal) is do
.. end - perimetro REAL is do
- Result 2 ( lado1 lado2 )
- end
- end -- class RECTANGULO
23Doble aspecto de la herencia
24Herencia y Subtipos
- Cuando B hereda de A, B tiene todos los atributos
y métodos de A - prop (A) ? prop (B)
- Cualquier objeto de B puede ser considerado
objeto de A - Siempre que se espera un objeto de A podemos
recibir un objeto de B, puesto que aceptaría
todos sus mensajes - Sea dom(C) el conjunto de instancias de una clase
C - dom (B) ? dom (A)
- B es un subtipo de A
25Herencia y Subtipos
A
Cualquier instancia de B puede actuar como
instancia de A
B
Herencia no es lo mismo que subtyping 1)
Subtyping sin herencia Dos clases que
representan complejos y no están relacionadas 2)
Herencia sin subtyping La clase Pila hereda de
la clase Cola
26Herencia y Subtipos
Circulo
Elipse
(a)
(a), (c), (d) herencia para compartir
código (b) herencia para especializar un tipo
27Herencia y sistema de tipos
A
metodo1
C
B
F
E
D
- oa A ob B oc C od D
- Son legales las siguientes asignaciones?
- oa ob oc ob oa od
- Es legal el mensaje od.metodo1?
28Polimorfismo
- Capacidad de una entidad de referenciar en tiempo
de ejecución (t.e.) a instancias de diferentes
clases. - Sean las declaraciones
- ox X haceAlgo (oyY)
- En un lenguaje con monomorfismo (Pascal, Ada, ..)
en t.e. ox y oy denotarán valores de los tipos X
e Y, respectivamente. - En un lenguaje con polimorfismo (Eiffel, C,
Java,..) en t.e. ox y oy pueden refeenciar
objetos de varios tipos diferentes. -
- tipo estático vs. tipo dinámico
29Polimorfismo
- Polimorfismo es restringido por la herencia
- Cada entidad puede estar conectada a instancias
de la clase asociada en su declaración o de
cualquiera de sus subclases. - Cada entidad tiene un tipo estático y un conjunto
de tipos dinámicos. - Sistema de tipos más flexible.
- Siempre que se espera un objeto de una clase
puede llegar uno de cualquiera de sus subclases - Importante para escribir código genérico
30Rutina polimorfa
- Posee entidades polimorfas parámetros, variables
locales. - Objeto actual (Current, this, self) puede ser una
entidad polimorfa. - Un mismo código con diferentes implementaciones
variación en implementación - maximo (v NUMERIC)
- mezclar (s SECUENCIAG)
- buscar (v G)
31Ejemplos rutina polimórfica
- maximo (v MAGNITUD) MAGNITUD is do
- if (Current gt v) then Result Current
- else Result v
- end
- comprendido (a,b MAGNITUD) BOOLEAN is do
- Result (altCurrent) and (Current gtb)
- end
32Polimorfismo
- Tipo estático
- Tipo asociado en la declaración
- Tipo dinámico
- Tipo correspondiente a la clase del objeto
conectado a la entidad en tiempo de ejecución - Conjunto de tipos dinámicos
- Conjunto de posibles tipos dinámicos de una
entidad
33Polimorfismo
A
C
B
F
E
D
- oa A ob B oc C
- te(oa) A ctd(oa) A,B,C,D,E,F
- te(ob) B ctd(ob) B, D, E
- te(oc) C ctd(oc) C,F
34Tipos de polimorfismo
- Real
- Paramétrico
- Inclusión (Basado en la herencia)
- Aparente
- Sobrecarga
- Ejemplo polimorfismo paramétrico
- long (plista) integer
- if pnil then long1
- else long 1 long(cola(p))
35Sobrecarga
- Nombre de una rutina es polimorfo.
- Se resuelve en tiempo de compilación, según la
signatura de la rutina. - No es necesario que exista similitud semántica.
- En los lenguajes OO puede existir sobrecarga
- dentro de una clase
- entre clases de una jerarquía (redefinición, es
fundamental) - entre clases no relacionadas
- C y Java proporcionan sobrecarga
- Polimorfismo complica la resolución de la
sobrecarga.
36Herencia y Sistema de tipos
- La herencia es consistente con el sistema de
tipos - Compatibilidad (Conforma)
- Tipos referencia
- T1 es compatible con T2 si la clase T1 es un
descendiente de la clase T2 - Tipos expandidos
- T1 es compatible con T2 si T1T2
- Tipos genéricos
- TG es compatible con TH si G es compatible
con H
37Herencia y Sistema de tipos
- Regla de la asignación
- Una asignación xy o una invocación r
(..,y,..) a una rutina r (.., xT,..), será legal
si el tipo de y es compatible con el tipo de x. - Regla de validez de un mensaje
- Un mensaje ox.r (y), supuesta la declaración ox
X, será legal si i) X incluye una propiedad con
nombre final r, ii) los argumentos son
compatibles con los parámetros y coinciden en
número, y iii) r está disponible para la clase
que incluye el mensaje.
38 p Poligono r Rectangulo c
Cuadrado asignación polimorfa p r
p.visualizar p.rotar (..) p.
perimetro pc
39Herencia y Sistema de tipos
- Sean las declaraciones
- p POLIGONO r RECTANGULO
- los siguientes mensajes son legales
- p.perimetro p.vertices p.trasladar (..)
p.rotar (..) - r.diagonal r.lado1 r.lado2
- r.vertices r.trasladar (..) r.rotar (..)
- r.perimetro
- los siguientes mensajes son ilegales
- p.lado1 p.lado2 p.diagonal
40- p POLIGONO r RECTANGULO t TRIANGULO... x
REAL - SERÍA CORRECTO EL CODIGO
- xp.perimetro
- xr.perimetro
- xr.diagonal
- if "algún test" then pr -- td(p)
RECTANGULO - else p t -- td(p) TRIANGULO
- end
- xp.perimetro
- PERO SERIA INCORRECTO EL CODIGO
- xp.diagonal
- rp
41Restricciones Justificadas?
- Tiene sentido que el compilador rechace el
código c1 y c2? - c1) p r r p
- c2) p r x p.diagonal
- Situaciones poco probables (sin sentido).
- Asignaciones como pr son normalmente ejecutadas
como parte de alguna estructura de control que
dependa de condiciones de tiempo de ejecución,
tal como la entrada de un usuario.
42- p POLIGONO r RECTANGULO t TRIANGULO... x
REAL - !!r.make !!t.make ..
- pantalla.visualizar_iconos
- pantalla.esperar_click_raton
- x pantalla.posicion_raton
- icono_elegido pantalla.icono_donde_esta_es(x)
- if icono_elegido icono_rectangulo then pr
- elsif pt
- elsif p"alguna otra clase de polígono"
- ...
- end
- ...
- uso genérico de la entidad p operaciones
aplicables a todas las variantes de poligonos - p.visualizar p. rotar (..)
43- Sea la rutina
- una_rutina (f FIGURA) is do .. end
- sólo tiene sentido aplicar sobre el parámetro f
operaciones aplicables sobre cualquier tipo de
polígono. -
- No se puede predecir el tipo exacto del objeto
conectado al parámetro f. - Sería un ejemplo de rutina polimorfa.
-
-
44Herencia y Sistema de Tipos
- La herencia es consistente con el sistema de
tipos. - En un lenguaje OO, toda la comprobación de tipos
debería ser estática, en tiempo de compilación
(Eiffel, Java). - La regla de aplicación de mensajes asegura que el
compilador sólo aceptará mensajes aplicables en
tiempo de ejecución. - Política pesimista compilador puede rechazar
código que tenga sentido en tiempo de ejecución. - Lenguajes tipados estáticamente son necesarios
para construir software fiable
45Polimorfismo en Smalltalk
- Polimorfismo sólo tiene sentido en un lenguaje
tipado estáticamente - En Smalltalk una variable puede concectarse en
tiempo de ejecución a un objeto de cualquier
clase (polimorfismo total). - p Poligono new.
- r Rectangulo new.
- 1)
- p r
- p.diagonal
- 2)
- rp
46Polimorfismo
- p POLIGONO
- r RECTANGULO
- !!p.crear (..) !!r. crear (..)
- ...
- p r
- Necesita semántica referencia
- Sólo una referencia puede ser polimorfa
p
r
47Genericidad y Polimorfismo
- Estructuras de datos polimorfas
- Pueden contener instancias de una jerarquía de
clases - Ejemplo
- fig ARRAY FIGURA
- p1, p2 POLIGONO r RECTANGULO c CIRCULO
- !!p1 !!p2 !!r !!c
-
- fig.put (p1,1) fig.put (r,2) fig.put (c,3)
fig.put (p2,4), ...
48Genericidad y Polimorfismo
fig
49Genericidad Restringida
- class VECTOR G feature
- count INTEGER
- item, infix _at_ (i INTEGER) is do .. end
- put(v G, iINTEGER) is do .. end
- infix (otro VECTORG) VECTORG is
- require count otro.count
- local i INTEGER
- do
- from i1 until igt count loop
- Result. put (item(i) otro.item(i), i)
- i i 1
- end
- end
- ....
- end -- class VECTOR
-
NO ES POSIBLE
50Genericidad Restringida
- Es posible restringir las clases a las que se
puede instanciar el parámetro genérico formal de
una clase genérica. - class C G -gt R
- Sólo es posible instanciar G con descendientes de
la clase R. - Ejemplos
- VECTOR G - gt NUMERIC
- DICTIONARY G, H - gt COMPARABLE
- ORDENACION G - gt COMPARABLE
- Permite aplicar operaciones sobre entidades cuyo
tipo es un parámetro genérico formal.
51Genericidad Restringida
- Sea la declaración
- VECTOR G -gt NUMERIC
-
- será posible aplicar operaciones de la clase
NUMERIC sobre entidades de tipo G - La genericidad no restringida equivale a G -gt ANY
- Sería legal la declaración x VECTOR VECTOR
G ?
52Ligadura dinámica
A
fA
redefine f
C
B
fB
redefine f
D
fD
Supuesto oa A, sea el mensaje oa.f(..), la
versión de f que se ejecuta depende del tipo
dinámico de oa.
53Ligadura dinámica
fA
A
?
redefine f
C
fC
?
B
fB
?
redefine f
D
fD
?
!!ob !!oc !!od oa ob oa.f oa oc
oa.f oa od oa.f
?
?
?
54Ligadura dinámica
- Que ocurre cuando aplicamos sobre una entidad
polimorfa una rutina con más de una versión? - Se ejecutará la versión de la rutina en la
clase que corresponda al tipo dinámico de la
entidad - La versión de una rutina en una clase es la
introducida por la clase (redefinición u
original) o la heredada.
55Ligadura dinámica
- p POLIGONO r RECTANGULO
- !!p x p.perimetro ? perimetroPOLIGONO
- !!r x r.perimetro ? perimetroRECTANGULO
- !!r p r x p.perimetro ?
perimetroRECTANGULO - Regla Ligadura Dinámica
- La forma dinámica del objeto determina que
versión de la rutina se aplicará
56Ligadura Dinámica Ejemplo
- visualizar (af ARRAY FIGURA) is do
- from i1 until i af.size loop
- af.item(i).dibujar
- end
- end
- Qué sucede si aparece un nuevo tipo de figura?
- Los clientes de cierta clase que ofrezca
diferentes implementaciones de cierta facilidad
pueden dejar al mecanismo de ejecución la
selección de la más apropiada, de modo
automático, en base a la forma de cada entidad
polimorfa
57Politica pesimista pero segura
- La regla de aplicación de propiedades puede
provocar que el compilador rechace mensajes
aplicables en tiempo de ejecución. - Sea el mensaje x.f (), la comprobación estática
de tipos garantiza que al menos existirá una
versión aplicable para f, y la ligadura dinámica
garantiza que se ejecutará la versión más
apropiada
58Esquemas de rutinas polimorfas (métodos genéricos)
- met1 is do
- ....
- Current.met2(..)
- ...
- end
- met3 (pA) is do //en otra clase
- ....
- p.met2(..)
- ....
- end
A
met1, met2
B
met2
C
met2
59Esquemas de rutinas polimorfas (métodos genéricos)
- met3 (p ARRAYA) is do
- from i1 until ip.size loop
- p.item(i).met2(..)
- end
- ..
- end
- met1(pA) is do
- ....
- current.met2()
- p.met2(..)
- ...
- end
A
met1, met2
B
met2
C
met2
60Ligadura dinámica en C
- Por defecto la ligadura es estática. Es necesario
declarar sobre qué funciones se aplicará ligadura
dinámica. - class A class B public A
- public public
- virtual void f () void f ()
//redefinición - ... ...
-
61Ligadura dinámica en C
- Uso de variables de tipo puntero para obtener
polimorfismo. - Declarar funciones virtuales para poder aplicar
ligadura dinámica. - A oa B ob // uso de variables tipo
puntero - ob new B()
- oa ob // asignación polimorfa
- oa -gt f () // f es una función virtual en A
62Ligadura dinámica en Smalltalk
- Al ser un lenguaje tipado dinámicamente la
ligadura entre el selector del mensaje y el
método debe ser dinámica. - Sólo en tiempo de ejecución podemos saber si un
mensaje es legal. - No se puede implementar tan eficientemente como
en un lenguaje OO tipado estáticamente.
63Ligadura dinámica
- Ahora está clara la diferente semántica entre la
llamada a un procedimiento y un mensaje - ob.f(op) vs. f(ob,op)
- En lenguaje tipado el coste de la ligadura
dinámica es pequeño y constante (independiente de
la profundidad de la jerarquía de herencia) - La ligadura estática es una optimización del
compilador, NO PUEDE SER LA OPCION POR DEFECTO.
64Ligadura dinámica
- Cuándo sé en C que debo declarar una rutina
como virtual? - Una rutina inline de C no puede ser virtual.
- En Eiffel, el compilador se encarga de detectar
situaciones que permiten aplicar código inline
(pequeñas, llamadas desde pocos lugares) y
ligadura estática.
65Ligadura dinámica
- En Eiffel y Java es posible declarar que un
método no puede ser redefinido. -
- public final void haceAlgo() ... (Java)
- frozen haceAlgo is do ... end (Eiffel)
- Importante restricción, se impide su adaptación
en una subclase. - En Java, es posible declarar una clase como final.
66Ligadura dinámica
67Problemas con el polimorfismo
- Perdemos información
-
- p POLIGONO r RECTANGULO
- !!r
- p r
- Ahora vemos un rectángulo como un polígono,
hemos perdido información sobre el tipo del
objeto - Los lenguajes proporcionan métodos para consultar
el tipo dinámico de una variable (p.e. instanceof
de Java). - No es recomendable ni habitual utilizarlos.
68Problemas con el polimorfismo
- Métodos que necesitan retornan un objeto de la
clase raíz (Object, ANY) - store (obj ANY, id STRING)
- retrieve (id STRING) ANY
-
- 2) Estructuras de datos polimorfas
- af ARRAYFIGURA
- or RECTANGULO !!or
- oc CIRCULO !!oc
- af.put(or,1) af.put(oc,2)
- af.item(i)
69Problemas con el polimorfismo
- p1,p2POLIGONO
- !!p1.crear(..)
- store (p1,miPoligono)
- ...
- p2 retrieve (p1, miPoligono)
Ilegal
70Ejemplo
- mayorDiagonal (lf LISTFIGURA) REAL is
- require lf / void
- do
- from lf.start Result -1.0 until lf.after
loop - if (lf.item.getClass Rectangulo) then
- Result Result.max(lf.item.diagonal) end
- lf.forth
- end
- end
Ilegal
71Ejemplo
- mayorDiagonal (lf LISTFIGURA) REAL is
- require lf / void
- local r RECTANGULO
- do
- from lf.start Result -1.0 until lf.after
loop - if (lf.item.getClass Rectangulo) then
- r lf.item
- Result Result.max(r.diagonal)
- end
- lf.forth
- end
- end
Ilegal
72Ejemplo
- mayorDiagonal (lf LISTFIGURA) REAL is
- require lf / void
- local r RECTANGULO
- do
- from lf.start Result -1.0 until lf.after
loop - r ? lf.item
- if r / void then Result Result.max(r.diagona
l) end - lf.forth
- end
- end
73Intento de asignación (Eiffel)
- Sintaxis
- oxX oy Y
- ox? oy
- Semántica
- 1) Es legal si X es compatible con Y
- 2) Se realiza la asignación en t.e. si el tipo
dinámico de oy es compatible con el tipo estático
de ox, X - 3) ox tendrá valor void si no se realiza la
asignación
74Conversión de tipos (Java)
- B ob (B) oa
-
- En tiempo de ejecución se comprueba si oa está
conectado a un objeto de B o una subclase de B. - Si falla la comprobación se lanza la excepción
ClassCastException.
if (oa instanceof B) ob (B) oa Se
comprueba antes el tipo dinámico con instanceof
para evitar la excepción ClassCastException
75Java y Genericidad
- Java no posee genericidad.
- Existen diversas propuestas para incluirla (
pre-procesadores del lenguaje). - En Java la forma de obtener estructuras de datos
genéricas es usando Object como el tipo base.
Esto presenta dos problemas - Cómo se asegura que una estructura de datos sea
homogénea? - Cómo podemos aplicar operaciones a los objetos
que se extraen?
76Java y Genericidad
- class Pila
- private Object elements
- private int count
- public Pila(int max)
- elements new Objectmax count -1
- public void put (Object v) elementscount
v - public Object item () return elementscount
- public void remove () count--
77Java y Genericidad
- class Nodo
- nodo right
- Object item
- ..
class Lista private nodo cabeza public
int count public Object item(int i)
.. public put (Object v int i) .. ..
78Class java.util.LinkedList
public class LinkedList extends
AbstractSequentialList implements
List, Cloneable, java.io.Serializable
private Entry header new Entry(null, null,
null) private int size 0 public
LinkedList() header.next
header.previous header private static
class Entry Object element Entry next
Entry previous Entry (Object element, Entry
next, Entry previous) this.element
element this.next next
this.previous previous
79Dos problemas
- 1) Las estructuras de datos pueden incluir
objetos de cualquier tipo la homogeneidad debe
asegurarla el programador. - 2) Cuando se extraen objetos almacenados en la
estructura de datos, es necesario hacer una
conversión de tipos (narrowing) para poder
aplicarle operaciones de la clase correspondiente.
80Eiffel vs. Java
Errores en compilación
Errores en ejecución
81Clases abstractas o diferidas
- Sea la declaración
- of FIGURA op POLIGONO
- y el código
- !!op
- ofop
- of.dibujar Sería legal?
- Cómo se implementa dibujar en la clase FIGURA?
82Clases abstractas
- Al aplicar la herencia, como mecanismo de
clasificación, aparecen clases que representan
categorías generales o conceptos abstractos, como
son "figura", colección, publicación",
dispositivo,... - Otras veces, dos clases comparten funcionalidad
pero no pueden ser declaradas una como subclase
de la otra - Qué operaciones incluyen?
- La rutina dibujar no puede ser implementada en
Figura pero of.dibujar es dinámicamente
correcto! -
-
- Solución MÉTODOS ABSTRACTOS
- (RUTINAS DIFERIDAS)
83Clases abstractas
- Contienen métodos abstractos que deben ser
implementados en sus subclases. - Puede ser total o parcialmente abstractas.
- Especifica una funcionalidad que es común a un
conjunto de subclases aunque no es completa. - No es posible crear instancias de una clase
abstracta, pero si declarar entidades de estas
clases. - Importantes para escribir código genérico.
84Las clases abstractas son un elemento del
lenguaje en los lenguajes tipados estáticamente
85Las clases abstractas no son necesarias como un
elemento del lenguaje en los lenguajes tipados
dinámicamente (p.e. Smalltalk)
- En Smalltalk
- Clase Figura sería la raíz de la jerarquía de
clases que representan figuras, pero no es
declarada como abstracta. - No tiene que incluir un método dibujar.
- Una regla de buen estilo de programación es
incluir los métodos abstractos con la
implementación - self implementedBySubclass
- En la clase Figura tendríamos el método
-
- dibujar
- self implementedBySubclass
86Clases abstractas en Smalltalk
- Por qué no son un elemento del lenguaje?
- Qué sucede si elimino un método implementado
como self implementedBySubclass ? - of Figura new. visualizar unaFigura
- of Poligono new. unaFigura dibujar
- of dibujar.
-
87Ejemplo
trasladar, rotar, ..
Figura
- En Figura
-
- trasladar (a,b REAL) is
- deferred
- end
Figura_Abierta
Figura_Cerrada
Segmento
Poligono
Elipse
Triangulo
Rectangulo
Circulo
Cuadrado
88La jerarquía de figuras
- La raíz es una clase abstracta
- deferred class FIGURA feature ... end.
- Una subclase de una clase abstracta puede seguir
siendo abstracta, si no implementa todos los
métodos abstractos heredados. - deferred class FIGURA_ABIERTA feature ... end
- deferred class FIGURA_CERRADA feature ... end
- Tendría sentido incluir dibujar en FIGURA como
un método que no hace nada, en vez de cómo un
método abstracto?
89Clases abstractas en C
- Una rutina abstracta f se declara como función
virtual pura virtual void f ( ) 0 - Ejemplo
- class figura
- public
- virtual void dibujar ( ) 0
- virtual void trasladar (..) 0
- ...
-
90Clases abstractas en C
- figura x // error
- figura x // legal
- figura f( ) // error
- void g (figura f) // error
- void h (figura f) // legal
91Clases parcialmente abstractas
- Contienen métodos abstractos y efectivos.
- Los métodos efectivos pueden invocar a los
métodos abstractos. - Son un importante medio para escribir código
genérico. - Incluyen comportamiento abstracto común a todos
los descendientes. - programs with holes
92Ejemplo
buscar , inicio fin, item,siguiente
TABLA_SECUENCIAL G
TABLA_FICHERO G
TABLA_ARRAY G
TABLA_ENLAZADA G
inicio, fin, item, siguiente
inicio, fin, item, siguiente
inicio, fin, item, siguiente
93Ejemplo
Esquema General o Patrón
- buscar(vT) Boolean is do
- from inicio until fin or else vitem loop
- siguiente
- end
- Result not fin
- end
- ta TABLA_ARRAY REAL
- ta.buscar (12.5)
Método plantilla
94Clases parcialmente diferidas
- Permiten capturar lo conocido sobre el
comportamiento y estructuras de datos que
caracterizan a cierta área de aplicación, dejando
una puerta abierta a la variación - SON UNA CONTRIBUCION IMPORTANTE DE LA OO A LA
REUTILIZACIÓN B. Meyer - Clases como TABLA_SECUENCIAL G que incluyen un
comportamiento común a varias subclases (familia
de implementaciones de TADs) se denominan - CLASES COMPORTAMIENTO
95Requerimientos de los módulos para facilitar la
reutilización
FUNCTION buscar (x Elemento t Coleccion)
BOOLEAN VAR pos Posición BEGIN pos
comenzar(x,t) WHILE not completa(pos,t) and
not encontrado(pos,t) DO possiguiente(pos,
x, t) buscarnot completa(pos,t) END
- 1. Variación en tipos.
- Aplicable a cualquier tipo de elemento (INTEGER,
FIGURA,..) - x elemento
96Requerimientos de los módulos para facilitar la
reutilización
2. Variación en estructuras de datos y
algoritmos. El tipo Coleccion puede estar
implementado de diferentes formas. siguiente(pos
,x,t) puede estar ligado a diferentes rutinas.
3. Independencia de la representación. Se puede
usar una operación sin conocer su
implementación siguiente(pos,x,t),
comenzar(x,t), encontrado(pos,t),
completa(pos,t)
4. Capturar similitudes entre un subgrupo de un
conjunto de posibles implementaciones. 5. Rutinas
relacionadas.
97Recomendación
- Programar hacia la interfaz no hacia la
implementación
A
X
Basado en una interfaz
C
B
X no tiene en cuenta las variantes de A X sólo
debe conocer la interfaz de A
98Método plantilla
99Ejercicio
- Diseña una clase ColeccionOrdenada cuyos objetos
son listas ordenadas de elementos de acuerdo a un
cierto criterio de ordenación que se establece al
crear la colección. Por ejemplo una lista de
cuentas podría ordenarse por saldo creciente o
alfabéticamente por el nombre del titular, entre
otros posibles criterios. - Escribe, en Eiffel y Java, la rutina add que
añade un elemento a la lista.
100Clases abstractas y Asertos
- En una clase diferida podemos especificar la
semántica del TAD asociado pre y postcondición
para cada rutina y el invariante de clase. - Eiffel es un lenguaje para todo el ciclo de vida
- Análisis / Diseño clases diferidas con asertos
- Implementación clases efectivas
101Clases abstractas con asertos
- deferred class STACKG feature
- count INTEGER
- remove is
- require not_empty
- deferred
- ensure
- count old count -1
- not full
- ...
- invariant
- empty (count 0)
- count gt 0
- end
102Herencia y Asertos
- Los asertos controlan el uso de la herencia.
- Redefinición y ligadura dinámica podrían usarse
de forma caprichosa. - Los asertos ayudan a comprender el significado de
la herencia. - Es una clase se siguen aplicando los asertos de
sus ascendientes. - Qué sucede con el invariante de la superclase?
- Qué sucede con las pre y postcondiciones en una
redefinición?
103Regla del Invariante
- Los invariantes de todas las superclases se
aplican sobre la clase.
puesto que B es un subtipo de A, siempre que
espero una instancia de A puedo recibir una
instancia de la clase B
104Precondiciones, postcondiciones y ligadura
dinámica
- Una redefinición no puede cambiar la semántica de
la rutina. - Una rutina que hace efectiva a una diferida debe
mantener la pre y postcondición. - Qué sucede en una redefinición?
- Aplicamos el diseño por contrato, teniendo en
cuenta la ligadura dinámica.
105Asertos y Redefinición
redefine r
// en class B r is require pre ensure
post end
// en class A r is require pre ensure
post end
106Asertos y Redefinición
- rutina (oa A) is do
- if oa.pre then oa.r else
-
- end
-
- REGLA DE LA REDEFINICION
- Podemos sustituir la precondición por una igual o
más débil. - Podemos sustituir la postcondición por una igual
o más fuerte.
Diseño Por Contrato
107Asertos y Redefinición
- Los asertos de una rutina expresan su semántica,
aplicable también a cualquier redefinición en un
descendiente. - Especifican un rango de comportamientos
aceptables por la rutina y sus redefiniciones. - Una redefinición puede especializar el rango pero
no violarlo. - Los asertos de una rutina diferida sólo deben
especificar propiedades abstractas.
108Asertos y Redefinición
- Cómo conseguimos una precondición más débil?
- Cómo conseguimos una postcondición más fuerte?
- Para cualquier ? y ?
- 1) ? implica ? or ?
- 2) ? and ? implica ?
109Asertos y Redefinición
// en A r is require pre ensure
post end
C
A
redefine r
B
// en B r is require else pre ensure
and post end
Precondicion rB pre or pre Postcondición rB
post and post
110Tiene sentido debilitar siempre la precondición?
put(x T) is require ??? ensure end
redefine put
put(x T) is require not llena ensure
end
111Herencia y Ocultación de Información
- La herencia expone los detalles de
implementación a las subclases - La herencia rompe la ocultación de información
Herencia (reutilización de caja blanca)
Cliente (reutilización de caja negra)
112Herencia y Ocultación de Información en Eiffel
En B se mantiene el status de exportación que las
características poseen en A. B puede
cambiar el status de exportación de cualquier
característica.
A
at1, at2 f, g
B
f exportada en A y B f privada en A y B f
exportada en A y oculta en B f oculta en A y
exportada en B
113Herencia y Ocultación de Información en Eiffel
class B inherit A export f //oculta f
que era exportado export g //exporta g que era
privado feature ... end
114Violación Ocultación Información en Eiffel
oaA ob B !!ob oa ob oa.f( )
A
f público
export f
B
f oculto
La asignación polimorfa permite aplicar sobre un
objeto de tipo B una operación f no disponible
el objeto puede quedar en un estado incosistente
115Herencia y Ocultación de Información en C y Java
- class A
- public
- // públicas accesibles desde todas las clases
- protected
- // protegidas sólo accesibles por la clase y
sus descendientes - private
- // privadas sólo visibles en la propia clase
- end
116Herencia y Ocultación de Información en Java
- Al redefinir es posible cambiar los
especificadores de acceso. - Una subclase puede cambiar el modificador de
acceso del método para hacerlo más accesible - protected a public, package a public o protected
- Si se hiciese menos accesible se violaría el
contrato de la superclase, ya que una instancia
de la superclase puede actuar en lugar de una de
la subclase.
117Herencia y Ocultación de Información en C
- Al redefinir es posible cambiar los
especificadores de acceso. - No existe la restricción de Java.
- Las propiedades private no pueden cambiar su
modificador de acceso no son visibles en la
subclase. - Se introduce la herencia privada para evitar la
violación de la ocultación de información de
Eiffel.
118Herencia Privada en C
- Herencia pública
- class B public A ..
- se mantiene el status de las propiedades
heredadas - Herencia privada
- class B private A ..
- todas las propiedades de A se heredan como
privadas y se impiden las asignaciones polimorfas
119Herencia Privada en C
class A public void f ( ) void g ()
protected... private... class B
private A public ... protected...
private...
A
f,g públicos
herencia privada
B
f,g privados
A oa B ob oa ob ERROR t.c. ob.f( )
ERROR t.c.
120Herencia Privada y Herencia de Implementación
- Dos principales categorías de herencia
- Especialización definición de subtipos
- Implementación capturar una implementación (se
puede cambiar por composición) - La herencia privada se utiliza para la herencia
de implementación.
ARRAY
FIGURA
PILA
POLIGONO
CIRCULO
Implementación
Especialización
121Herencia Privada y Herencia de Implementación
Array
put, item
Pila op new Pila() Array oa oa op
Error T.C. ob. put(3,120) Error T.C.
herencia privada
Pila
push, pop, top
122Por qué la política de Eiffel?
- Flexibilidad y Extensibilidad
- La herencia es la encarnación del principio
abierto-cerrado - La propiedad básica de la herencia es permitir
definir descendientes de una clase no previstos
en su creación. - Cómo sabemos a priori que propiedades exportará
o no una subclase no prevista? - La herencia sólo debe estar limitada por los
asertos y las reglas de tipado.
123Ocultar propiedades en las subclases
POLIGONO
añadirVertice
HIPOTECA
amortizar
ocultar añadirVertice
ocultar amortizar
RECTANGULO
NUEVA_HIPOTECA
A menudo es inevitable que una clase deba ocultar
alguna propiedad heredada de la
superclase. Eiffel Lo permite Java No lo
permite C Lo permite, sin tener que aplicar la
herencia privada
124Ocultar un método en una subclase en Java
A
public void f() ..
public void f() throw new UnsupportedOperationE
xception()
B
A oa B new B() oa ob oa. f()
Se lanza una excepción
125Ejercicio
- Sea la clase Stack de la librería de Java que
hereda de Vector y que modela la estructura de
datos pila - public class Stack extends Vector
- public Object push (Object item)
- addElement (item) return item
- public Object peek ()
- return elementAt(size() - 1)
- public Object pop ()
- Object obj peek ()
- return removeElementAt(size() - 1)
- return obj
-
-
-
- Cómo evitarías que se pudiese manejar una pila
a través de los métodos heredados de Vector,
tales como insertElementAt(Object obj, int index)
que añade el elemento obj en la posición index o
el método elementAt(int index) que retorna el
objeto en la posición index?
126Herencia y Creación
- Los constructores de C y Java no son heredados
por las subclases. - En Eiffel, las rutinas de creación pierden ese
status. -
A
at1, at2
INVA
Nuevo invariante
Nuevos atributos
INVB
B
at3, at4
127Herencia y Creación en C
- En C, un constructor invoca al constructor por
defecto de la clase padre o a uno especificado
explícitamente. -
A
A (), A( int x)
B (int x, int y) A(x)
B
128Herencia y Creación en Java
- Un constructor puede invocar a un constructor de
la superclase con super, por defecto se invoca al
constructor sin argumentos super() -
A
int at1 A(int i) at1 i
Object at2 B(int i) super(i) at2
null
B
129Herencia y creación en Eiffel
- fig FIGURA tri TRIANGULO circ CIRCULO seg
SEGMENTO - tipo_icono_sel INTEGER p1, p2, p3 PUNTO
- tipo_icono_sel interface. icon_selected
(mouse_position) - inspect tipo_icono_sel
- when segmento_icono then !!seg.make (p1,p2)
fig seg - when circulo_icono then !!circ.make (p1,radio)
fig circ - when triangulo_icono then !!tri.make (p1,p2,p3)
fig tri - ...
- end
- fig. visualizar
130Herencia y creación en Eiffel
- fig FIGURA tipo_icono_sel INTEGER p1, p2, p3
PUNTO - tipo_icono_sel interface. icon_selected
(mouse_position) - inspect tipo_icono_sel
- when segmento_icono then !SEGMENTO! fig. make
(p1,p2) - when circulo_icono then !CIRCULO! fig. make
(p1,radio) - when triangulo_icono then !TRIANGULO! fig. make
(p1,p2,p3) - ...
- end
- fig. visualizar
131Herencia Múltiple
- Más difícil de usar e implementar que la herencia
simple. - Es conveniente?
- Algunos consideran que produce más inconvenientes
que ventajas Java no incluye herencia múltiple
de clases! - 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
herencia múltiple es necesario considerar el
doble aspecto de la herencia definición de
subtipos y extensión modular
132Herencia Múltiple y Extensión modular
STORABLE
R
MATH
R
S
S
En Eiffel
- S es una especialización de R
- MATH incluye un paquete de rutinas matemáticas
- STORABLE ofrece servicios de persistencia de
objetos
En Java se usa una clase con propiedades
estáticas que ofrecen los servicios
133 Herencia Múltiple y Subtyping
ESTUDIANTE
PROFESOR
PROFESOR_ AYUDANTE
Los profesores ayudantes están matriculados de
cursos de doctorado
134Herencia Múltiple y Subtyping
CON_INTERESES
BIENES
ASEGURABLE
CUENTA_ BANCARIA
VALORES
ACCIONES
CUENTA_ AHORRO
BIENES_ INMUEBLES
BONOS
CUENTA_ CORRIENTE
135Herencia Múltiple y Subtyping
- Implementación de los menús de una aplicación
- i) Los menús son simples
- MENU ARRAY OPCION_MENU
- ii) Los menus contienen submenus
- 1) MENU TREE OPCION_MENU
- provocaría muchos cambios
- 2)
MENU
OPCION_MENU
menu, ejecutar
num_opciones display, opciones
SUBMENU
ejecutar
136Herencia Múltiple y Subtyping
CUENTA_ BANCARIA
CUENTA_ CORRIENTE
CUENTA_ AHORRO
Qué hacemos si surge un nuevo tipo de cuenta que
comparte propiedades de una cuenta de ahorro y
una cuenta corriente?
137Con herencia múltiple
CUENTA_ BANCARIA
CUENTA_ CORRIENTE
CUENTA_ AHORRO
NUEVA_ CUENTA
138Sin herencia múltiple
CUENTA_ BANCARIA
CUENTA_ CORRIENTE
CUENTA_ AHORRO
NUEVA_ CUENTA
Debemos añadir a NUEVA_CUENTA las propiedades de
CUENTA_CORRIENTE.
139Herencia Múltiple y Subtyping
MAGNITUDE
, lt, gt, ..
, -, , / ..
NUMBER
CHAR
INTEGER
Deseamos añadir en la jerarquía de clases de
Smalltalk una clase que representa números
complejos
140Clase Complejo
MAGNITUDE
COMPARABLE
NUMBER
NUMBER
CHAR
INTEGER
CHAR
COMPLEJO
OPCION 2
INTEGER
COMPLEJO
OPCION 1
141Problemas con la Herencia Múltiple
f
B
A
f
C
Solución en Eiffel - Se considera un problema
sintáctico - Debe ser resuelto por la clase que
hereda - La clase C necesitaría RENOMBRAR al
menos una de las dos características
heredadas que colisionan
142Problemas con la H. Múltiple
class C inherit A rename f as af B rename
f as bf feature ... end
f
B
f
A
C
af, bf
No hay colisión de nombres si i) colisiona una
rutina diferida con otra efectiva ii) hay
herencia repetida con compartición
143Colisión de nombres en C
- No es posible renombrar
- Como se resuelve la colisión de nombres?
- Calificación de rutinas
f ()
f ()
B
A
C oc oc -gt Af ( ) oc- gt Bf ( )
C
- Solución poco adecuada para los clientes
144Calificación de rutinas en C
- class A
- virtual void f ()
- ...
-
- class B
- void g () ... oa-gtAf () ...
- ...
-
- Af () puede aplicarse desde cualquier clase
Elimina la ligadura dinámica
145Problemas con la H. Múltiple
f
A
D es descendiente de A por más de un camino
C
B
D
Qué sucede con las propiedades heredadas más de
una vez? REPLICACION o COMPARTICION
146Matrimonio por conveniencia
- Proporcionar una implementación para una
abstracción definida por una clase diferida
LINKED_LIST G
put
PILA G
ARRAY G
put
put
export NONE all
export NONE all
PILA_ENLAZADA G
PILA_FIJA 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.
147- class PILA_FIJA G inherit
- PILA G
- ARRAY G
- export NONE all
- rename put as array_put, make as make_array,
count as capacity - creation make
- feature
- count INTEGER - - rutina diferida se
redeclara como atributo - make (n INTEGER) is
- require tamaño_no_negativo ngt0
- do
- array_make (1,n)
- ensure
- capacidad capacity n
- vacia count 0
- end
-
- -- continua página siguiente
148- full BOOLEAN is do
- Result (count capacity)
- end
- put (x G) is
- require not full
- do
- count count 1
- array_put (x, count)
- end
- ...
- invariant
- countgt0 count lt capacity
- ...
- end -- PILA_FIJA G
149Violación ocultación de información
- Sea la declaración
- op PILA_FIJA INTEGER
- entonces
- op.array_put (32,45)
- provocaría error en tiempo de compilación.
- Sería legal el siguiente código?
- op PILA_FIJA INTEGER oa ARRAY INTEGER
- ...
-
- op. put (32,45)
- oa op
- oa. put (32,45)
150Composición versus Matrimonio por conveniencia
PILA G
put, item
imp
ARRAY G
PILA_FIJA G
put, item
full BOOLEAN is do Result (count
imp.capacity) end put (x G) is do count
count 1 imp.put (x, count) end
151Composición vs. Matrimonio por Conveniencia
- 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. - Cuando 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.
152Herencia de Estructura
- Se desea que una clase posea ciertas propiedades
además de la abstracción que representa.
STORABLE
COMPARABLE
DIAGRAMA
NUMERIC
DIAGRAMA_ CLASES
INTEGER
153Herencia de Facilidades
- Existen clases que existen con el único propósito
de ofrecer unos servicios a sus descendientes
ASCII
A
A
MATH
ITERATOR
A
B
B
B
154Figuras Compuestas
- class FIGURA_COMPUESTA inherit
- FIGURA
- LINKED_LIST FIGURA
- feature
-
- end
- Una figura compuesta es una figura
- una figura compuesta es una lista de figuras
155Figuras Compuestas
- Incluirá las operaciones aplicables sobre
figuras trasladar, rotar, visualizar, - visualizar is do
- from start until after loop
- item.display
- forth
- end
- end
- Muchas rutinas con esta estructura
156Combinación de interfaces no relacionadas
- 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
157Combinación de interfaces no relacionadas
- class TREE G inherit
- LIST G
- LINKABLE G
- feature
- ....
- end
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
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...
158Adaptaciones al heredar
- Redefinir
- Renombrar (Eiffel)
- Resolver ambigüedades en los nombres de las
características - Hacer efectiva una rutina
- Cambiar el tipo de un atributo o un parámetro de
una rutina (Eiffel) - Combinar características
- Cambiar el status de visibilidad de una
característica - Convertir en diferida una rutina efectiva
(Eiffel) - Eliminar conflictos de ligadura dinámica cuando
existe herencia repetida
159Redefinición
- Reconcilia la reutilización con la
extensibilidad - Es raro reutilizar un componente software sin
necesidad de cambios - Podríamos redefinir
- tipo de un parámetro o atributo (sólo en Eiffel)
- Pre y Postcondiciones (sólo en Eiffel)
- Excepciones que lanza (Java)
- Implementación
- Se debe mantener la semántica de la rutina
original
160Necesidad de redefinir
A
at1, at2, f
INVA
Nuevo invariante
Nuevas propiedades
B
INVB
at3, at4, f, g
Mejorar implementación de f
161Necesidad de redefinir
LISTA G
ELIPSE
escala()
insertar (vG)
redefine escala
redefine insertar
escala()
LISTA_ORDENADA G
CIRCULO
insertar (vG)