Publicado el 7 de Julio del 2017
866 visualizaciones desde el 7 de Julio del 2017
420,7 KB
24 paginas
Creado hace 17a (03/12/2007)
Programación Orientada a Objetos
TEMA 3
Herencia
(2ª parte)
Facultad de Informática
Universidad de Murcia
Índice
1.- Introducción
2.- Adaptaciones del lenguaje:
- Redefinición vs. Renombramiento
- Cambios en el nivel de visibilidad
3.- Herencia y creación
4.- Polimorfismo y ligadura dinámica
5.- Genericidad
- Estructuras de datos polimórficas
- Genericidad restringida
6.- Clases abstractas/diferidas
2
•1
1.-Introducción
• La herencia es un mecanismo que posibilita la
definición de una clase a partir de otra dando soporte
para
relaciones de
especialización o generalización existentes entre las
clases.
registrar y utilizar
las
• La herencia organiza las clases en una estructura
jerárquica que puede tener o no una clase raíz:
– Java:
– Eiffel:
– C++:
– C#:
clase Object
clase ANY
no existe una clase raíz
clase System.Object
Tema4: Herencia
1.- Introducción
• Terminología:
– B hereda de A
– Java:
• B es subclase de A
• A es superclase de B
– Eiffel:
• B es descendiente de A
• A es un ascendiente de B
– C++:
• B es una clase derivada de A
• A es la clase base de B
– C#:
• B es la clase hija de A
• A es la clase padre o clase base de B
Tema4: Herencia
3
4
•2
2.- Adaptaciones del lenguaje
• Cuando una clase B hereda de una clase A:
– B puede añadir nuevos atributos
– B puede añadir nuevos métodos
– B puede redefinir los métodos de A
• Refinamiento vs. Reemplazo
– B puede renombrar los métodos de A
– B puede implementar métodos abstractos de A
– B puede cambiar el nivel de visibilidad de los
atributos y métodos heredados
• Las adaptaciones dependen del lenguaje
Tema4: Herencia
Adaptaciones en Eiffel
• Renombramiento:
– Cambiamos el nombre de la característica
– Es un mecanismo sintáctico
– Cláusula rename
– Utilidad:
• Solucionar las colisiones de nombres
• Proporcionar nombres más adecuados
• Redefinición:
– Cambiamos la versión de la característica
– Es un mecanismo semántico
– Cláusula redefine
– Utilidad:
• Refinamiento
• Reemplazo
Tema4: Herencia
5
6
•3
Ejemplo renombramiento
class Pila
inherit Array
rename
put as array_put,
remove as array_remove,
end
....
end
Tema4: Herencia
7
Renombrar & Redefinir
• Una característica con nombre final f en la clase C
podrá tener un nombre original g distinto en la clase
origen A dónde se introdujo inicialmente.
• Cada característica f de una clase C tiene un nombre
final en C, que se define según
– Si f es inmediato:
nombre final = nombre original
– Si f es heredado de A y no se renombra:
nombre final = nombre final en A
– Si f es heredado de A y se renombra
nombre final = “nuevo nombre”
Tema4: Herencia
8
•4
Combinar redefinir y renombrar
B {fα,gδ,hφ}
C {nfβ, gγ, hφ}
class C inherit
B
rename f as nf
redefine g, nf
end;
feature
nf is do .. end;
g is do .. end;
...
end
-- debe ir antes de redefine
Clase
donde
está
Clase
origen
Nombre
final
Nombre
original Versión
B
B
B
C
C
C
B
B
B
B
B
B
f
g
h
nf
g
h
f
g
h
f
g
h
α
δ
φ
β
γ
φ
* Ejercicio 1:
{fα}
A
rename f as g
B
{gα}
* Ejercicio 2:
{fα}
A
rename f as g
redefine g
B
{gβ}
Tema4: Herencia
oa: A; ob: B
!!ob
oa:= ob
oa.f
oa.g
ob.f
ob.g
-- {α}
-- {error t.c.}
-- {error t.c.}
-- {α}
oa: A; ob: B
!!ob
oa:= ob
oa.f
oa.g
ob.f
ob.g
-- {β}
-- {error t.c.}
-- {error t.c.}
-- {β}
10
•5
* Ejercicio 3:
B
{fα, gβ}
rename f as h
redefine h
C
{hδ, iγ }
-- se ejecuta α
-- se ejecuta β
ob: B; oc: C
!!ob;
ob.f ()
ob.g()
ob:= oc
ob.f ()
ob.i ()
oc.h () -- se ejecuta δ
oc.f ()
-- se ejecuta δ
-- error en compilación
-- error en compilación
Clase
B
B
C
C
C
Nombre final
Nombre original Versión Clase Origen
f
g
h
g
i
f
g
f
g
i
α
β
δ
β
γ
B
B
B
B
C
Tema4: Herencia
11
Ejercicio 4
class C inherit
A
B
rename f as g;
rename f as h;
redefine h;
feature
h is do … end
f is do … end
end
oa: A; ob: B; oc: C;
!!oc;
oc.f;
oc.g;
oc.h;
oa:= oc;
oa.f;
oa.g;
ob:= oc;
ob.f;
ob.h;
Tema4: Herencia
12
•6
Redefinición en Eiffel
• ¿Qué podemos cambiar?
– Tipo de las características (Regla covariante)
– Implementación
• Solicita explícitamente mediante la cláusula redefine.
• No es necesario incluirlo cuando se redefine para hacer efectiva una
característica.
• Técnicas que le añade potencia:
a)Redefinir una función como un atributo
• Aplicación del Principio de Acceso Uniforme
• Un atributo no se puede redefinir como una función
b)El uso de la versión original en una redeclaración
• “Facilita la tarea al que redefine si el nuevo trabajo incluye el viejo”.
13
Tema4: Herencia
Ejemplo: Regla covariante en Eiffel
sustituto
Dispositivo
Impresora
sustituto
Regla de Redeclaración de Tipo (Eiffel)
Una redeclaración de una característica puede reemplazar el tipo de la
característica (si es un atributo o una función), o el tipo de un argumento
formal (si es una rutina) por cualquier tipo compatible con el original.
Tema4: Herencia
14
•7
Ejemplo: Redefinir una función como un atributo
Result:= ingresos.total -reintegros.total
class Cuenta1 feature
saldo: INTEGER is do
end
...end
class Cuenta2 inherit
feature
...end
Cuenta1 redefine saldo end
saldo:INTEGER
Tema4: Herencia
15
Uso de la versión original en Eiffel
• Entidad Precursor = llamar a la versión de esta característica
en la clase padre.
• Su uso está limitado al cuerpo de las rutinas redefinidas
– ¿Equivale a super en Java?
• Ejemplo: Dibujar un botón es mostrarlo como una ventana y luego dibujar
el borde
VENTANA
dibujar is do ... end
BOTON
dibujar is do
Precursor
dibujar_borde
end
Tema4: Herencia
16
•8
Herencia y Ocultación de Información en Eiffel
• Son mecanismos independientes
• Una clase B es libre de exportar o de esconder una característica
f que hereda de un antecesor A.
A {f}
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
• Por defecto f mantiene el status de exportación que tenía en A,
pero se puede cambiar mediante la clausula export.
Tema4: Herencia
17
¿Por qué dejar que cada descendiente escoja la
política de exportación en Eiffel?
• Flexibilidad y Extensibilidad:
– La herencia es la clave 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.
Tema4: Herencia
18
•9
“Agujero de tipos” en Eiffel
• Violación del sistema de
tipos debido a las
asignaciones polimórficas
Array
put(elem, index)
remove(elem, index)
rename …
export{NONE}ALL
put(elem)
remove(elem)
Pila
Sea la declaración:
p: PILA[INTEGER]
p.array_put(32,45) //Error tc
¿Provocaría un error el
siguiente código?
a: ARRAY [INTEGER]
...
a:= p
a.put (32,45)
¿Cuál es la alternativa a la herencia de implementación?
Tema4: Herencia
19
Redefinición en C++
• Clase base contiene una función virtual vf
• Clase que se deriva de ella contiene una función vf del mismo tipo (si son distintos
se consideran funciones diferentes y no se invoca al mecanismo virtual)
class Base {
virtual void vf1();
virtual void vf2();
virtual void vf3();
void f();
//Ligadura dinámica
//Derivada::vf1
//Base::vf2
//Base::f
//ERROR
20
•10
void g()
{
Derivada *d;
Base* b;
...
b = d;
b -> vf1();
b -> vf2();
b -> f();
d-> vf2();
...
//Ligadura estática
};
class Derivada : public Base {
//redefine vf1
//distinta a vf2()
//error, difiere tipo devuelto
void vf1();
void vf2 (int);
char vf3();
void f();
};
• Llamada al padre calificando las rutinas. Ej: Base :: f()
}
Herencia y Ocultación de Información en C++
• protected:
– sólo accesibles por la clase y sus descendientes
• Tipos de herencia:
– Herencia privada:
class B: private A {...}
• todas las propiedades de A se heredan como privadas
• se puede mantener el estatus calificando la rutina
– Herencia pública:
class B: public A {...}
• se mantiene el status de las propiedades heredadas (por defecto)
• un miembro private o protected no puede ser re-exportado, es
decir, protected no puede ser public y private no puede ser
ni protected ni public
• “agujero” debido asignaciones polimórficas (público puede pasar a
privado)
Tema4: Herencia
21
Herencia y exportación en C++
Se puede conservar el acceso si la herencia es privada, mencionando
su nombre calificado en la parte public o protected. Por
ejemplo:
class B{
int a; //private
public:
int bf();
protected:
int c;
};
class D: private B{
Todos los miembros de
B son privados en D
public:
B::bf(); //hace que bf sea público en D
//ERROR intenta conceder acceso
B::a;
protected:
B::bf(); //ERROR intenta reducir acceso
};
Tema4: Herencia
22
•11
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:...}
Tema4: Herencia
23
Redefinición en C#
class Punto2D {
...public virtual string ToString(){
return “[” + x+ “,” + y + “]”;
}
...
}class Punto3D : Punto2D {
...public override string ToString(){
}
}
return base.ToString() + “[z=“ + z +”]”;
• Si se nos olvida poner override se entiende que estamos
ocultando el método de la clase padre.
• Toda redefinición de un método debe mantener el mismo nivel de
acceso que tuviese el método original.
Tema4: Herencia
24
•12
Redefinición y ocultación en C# (1/2)
using System;
class A {
}
class B : A {
}
class C : B {
}
class D : C {
public virtual void F(){ Console.WriteLine(“A.F”);
public override void F(){ Console.WriteLine(“B.F”);
new public virtual void F(){Console.WriteLine(“C.F”);
public override void F(){ Consol
Comentarios de: TEMA 3 Herencia (2ª parte) (0)
No hay comentarios