Publicado el 17 de Julio del 2017
1.371 visualizaciones desde el 17 de Julio del 2017
1,1 MB
100 paginas
Creado hace 14a (18/01/2011)
Programación orientada a objetos
TEMA 3
HERENCIA
Cristina Cachero, Pedro J. Ponce de León
versión 3
(Curso 10/11)
(3 sesiones)
POO
Tema 3. HERENCIA
Objetivos
Entender el mecanismo de abstracción de la herencia.
Distinguir entre los diferentes tipos de herencia
Saber implementar jerarquías de herencia en C++
Saber discernir entre jerarquías de herencia seguras (bien definidas) e
inseguras.
Reutilización de código: Ser capaz de decidir cuándo usar herencia y
cuándo optar por composición.
2
Herencia
Del tema anterior…
Persistente
No persist.
Entre objetos
Asociación
Todo-Parte
Agregación
Composición
Entre clases
Generalización
C1
C2
Uso (depend)
C1
C2
3
vehiculo aéreoavionhelicopteroHERENCIA
Motivación
Florista
cobrar()
darRecibo()
Panadero
cobrar()
darRecibo()
. . . .
Vendedor
coches
cobrar()
darRecibo()
Asociamos ese
comportamiento
a una categoría
general
(generalización)
Dependiente
cobrar()
darRecibo()
CLASE DERIVADA (C++)
CLASE HIJA
SUBCLASE
CLASE BASE (C++)
CLASE PADRE
SUPERCLASE
4
Clasificación y generalización
La mente humana clasifica los conceptos de acuerdo a dos
dimensiones:
Pertenencia (TIENE-UN) -> Relaciones todo-parte
Variedad (ES-UN) -> Herencia
La herencia consigue clasificar los tipos de datos
(abstracciones) por variedad, acercando un poco más el
mundo de la programación al modo de razonar humano.
Este modo de razonar humano se denomina GENERALIZACIÓN,
y da lugar a jerarquías de generalización/especialización.
La implementación de estas jerarquías en un lenguaje de
programación da lugar a jerarquías de herencia.
5
Herencia como implementación de la
Generalización
La generalización es una relación semántica entre
clases, que determina que la interfaz de la subclase
debe incluir todas las propiedades públicas y privadas
de la superclase.
Disminuye el número de relaciones (asociaciones y
agregaciones) del modelo
Aumenta la comprensibilidad, expresividad y
abstracción de los sistemas modelados.
Todo esto a costa de un mayor número de clases
7
HERENCIA
Definición
La herencia es el mecanismo de implementación mediante el cual
elementos más específicos incorporan la estructura y comportamiento
de elementos más generales (Rumbaugh 99)
Gracias a la herencia es posible especializar o extender la funcionalidad de
una clase, derivando de ella nuevas clases.
La herencia es siempre transitiva: una clase puede heredar características
de superclases que se encuentran muchos niveles más arriba en la jerarquía
de herencia.
Ejemplo: si la clase Perro es una subclase de la clase Mamífero, y la clase Mamífero
es una subclase de la clase Animal, entonces el Perro heredará atributos tanto de
Mamífero como de Animal.
8
HERENCIA
Test “ES-UN”
La clase A se debe relacionar mediante herencia con la
clase B si “A ES-UN B”. Si la frase suena bien, entonces
la situación de herencia es la más probable para ese caso
Un pájaro es un animal
Un gato es un mamífero
Un pastel de manzana es un pastel
Una matriz de enteros es un matriz
Un coche es un vehículo
9
HERENCIA
Test “ES-UN”
Sin embargo, si la frase suena rara por una razón u otra,
es muy probable que la relación de herencia no sea lo más
adecuado. Veamos unos ejemplos:
Un pájaro es un mamífero
Un pastel de manzana es una manzana
Una matriz de enteros es un entero
Un motor es un vehículo
10
HERENCIA
Principales usos
La herencia como reutilización de código: Una clase
derivada puede heredar comportamiento de una clase
base, por tanto, el código no necesita volver a ser escrito
para la derivada.
Herencia de implementación
La herencia como reutilización de conceptos: Esto ocurre
cuando una clase derivada sobrescribe el
comportamiento definido por la clase base. Aunque no se
comparte ese código entre ambas clases, ambas
comparten el prototipo del método (comparten el
concepto).
Herencia de interfaz
11
Tipos de Herencia
Simple/Múltiple
De implementación/de interfaz
12
Tipos de Herencia
Simple/Múltiple
Simple: única clase base
Múltiple: Más de una clase base
13
Tipos de Herencia
De implementación/de interfaz
De implementación: La implementación de los
métodos es heredada. Puede sobreescribirse en las
clases derivadas.
De interfaz: Sólo se hereda la interfaz, no hay
implementación a nivel de clase base (interfaces en
Java, clases abstractas en C++)
14
Herencia
Caracterización semántica
Atributos de la generalización
Solapada/Disjunta
Determina si un objeto puede ser a la vez instancia de dos o más subclases de
ese nivel de herencia.
C++ no soporta la herencia solapada (tipado fuerte)
Completa/Incompleta
Determina si todas las instancias de la clase padre son a la vez instancias de
alguna de las clases hijas (completa) o, por el contrario, hay objetos de la clase
padre que no pertenecen a ninguna subcategoría de las reflejadas por las clases
hijas (incompleta).
Estática/Dinámica
Determina si un determinado objeto puede pasar de ser instancia de una clase
hija a otra dentro de un mismo nivel de la jerarquía de herencia.
C++ no soporta la herencia dinámica (tipado fuerte)
16
Herencia
Caracterización: ejemplos
17
HERENCIA DE IMPLEMENTACIÓN
Herencia Simple
Herencia Simple en C++
Mediante la herencia, las propiedades definidas en una clase base
son heredadas por la clase derivada.
La clase derivada puede añadir propiedades específicas
(atributos, métodos o roles)
19
Herencia Simple en C++
class Figura2D {
public:
...
void setColor(Color c);
Color getColor() const;
private:
Color colorRelleno;
... };
class Circulo : Figura2D {
...
public:
void vaciarCirculo() {
colorRelleno=NINGUNO;
// ¡ERROR! colorRelleno es privado
setColor(NINGUNO); // OK
}
};
La parte privada de una clase base no es
directamente accesible desde la clase
derivada.
int main() {
Circulo c;
c.setColor(AZUL);
c.getColor();
c.vaciarCirculo();
...
}
20
Herencia en C++
Visibilidad atributos/métodos
Ámbito de visibilidad protected
Los datos/funciones miembros protected son directamente accesibles desde
la propia clase y sus clases derivadas. Tienen visibilidad privada para el
resto de ámbitos. En UML, se especifica con ‘#’.
class Figura2D {
protected:
Color colorRelleno;
...
};
int main () {
Circulo c;
c.colorRelleno=NINGUNO;
// ¡ERROR! colorRelleno
// es privado aquí
}
class Circulo : Figura2D {
public:
void vaciarCirculo() {
colorRelleno=NINGUNO; //OK, protected
}
...
};
21
Tipos de Herencia Simple (en C++)
Herencia Pública (por defecto)
class Circulo : public Figura2D {
...
};
Herencia Protegida
class Circulo : protected Figura2D {
...
};
Herencia Privada
class Circulo : private Figura2D {
...
};
<<public>>
<<protected>>
<<private>>
22
Tipos de Herencia Simple
Ámbito
Herencia
Visibilidad
en clase base
Private
Protected
CD (*)
H. Pública
No direct.
accesible
Protected
CD
H. Protegida
No direct.
accesible
Protected
CD
H. privada
No direct.
accesible
Private
Public
Public
Protected
Private
(*) CD: Clase derivada
23
Tipos Herencia Simple
Ejercicio
Abuela
+ publico: int
# protegido: int
- privado: int
+ setPublicoAbuela(int)
+ setProtegidoAbuela(int)
+ setPrivadoAbuela(int)
+ inicializaTodoAUno();
Padre
<<??>>
+inicializaTodoAUno()
<<public>>
Implementa el método
Hija::inicializaTodoAUno() suponiendo
que la herencia entre Abuela y Padre es:
•Pública
•Protegida
•Privada
Hija
+inicializaTodoAUno()
24
Herencia Simple
Métodos en las clases derivadas
En la clase derivada se puede:
Añadir nuevos métodos/atributos propios de la clase derivada
Modificar los métodos heredados de la clase base
REFINAMIENTO: se añade comportamiento nuevo antes
y/o después del comportamiento heredado. (Simula, Beta)
(se puede simular en C++, Java)
C++, Java: Constructores y destructores se refinan
REEMPLAZO: el método heredado se redefine
completamente, de forma que sustituye al original de la
clase base.
26
El constructor en herencia simple
Los constructores no
se heredan
Siempre son definidos para
las clases derivadas
Creación de un objeto de
clase derivada: Se invoca a
todos los constructores de
la jerarquía
Orden de ejecución de
constructores: Primero se
ejecuta el constructor de la
clase base y luego el de la
derivada.
27
El constructor en herencia simple
A
B
C
28
El constructor en herencia simple
Esto implica que la clase derivada aplica una
política de refinamiento: añadir comportamiento
al constructor de la clase base.
Ejecución implícita del constructor por defecto de
clase base al invocar a un constructor de clase
derivada.
Ejecución explícita de cualquier otro tipo de
constructor en la zona de inicialización
(refinamiento explícito). En particular, el
constructor de copia.
(CONSEJO: Inicialización de atributos de la clase base: en
la clase base, no en la derivada)
29
El constructor en herencia simple
Ejemplo
class Figura2D {
Color colorRelleno;
public:
Figura2D() : colorRelleno(NINGUNO) {}
Figura2D(Color c) : colorRelleno(c) {}
Figura2D(const Figura2D& f)
: colorRelleno(f.colorRelleno) {}
...};
class Circulo : Figura2D {
double radio;
public:
Circulo() : radio(1.0) {} //llamada implícita a Figura2D()
Circulo(Color col, double r) : Figura2D(col), radio(r) {}
Circulo(const Circulo& cir)
: Figura2D(cir), radio(cir.radio) {}
...};
30
El destructor en herencia simple
El destructor no se
hereda.
Siempre es definido para
la clase derivada
Destrucción de un objeto
de clase derivada: se
invoca a todos los
destructores de la
jerarquía
Primero se ejecuta
destructor de la clase
derivada y luego el de la
clase base.
Llamada implícita a los
destructor de la clase
base.
31
El destruc
Comentarios de: POO 3 Herencia (0)
No hay comentarios