Documentos de Académico
Documentos de Profesional
Documentos de Cultura
TEMA 3
HERENCIA
Cristina Cachero, Pedro J. Ponce de Len
versin 3
(Curso 10/11)
(3 sesiones)
POO
Tema 3. HERENCIA
Objetivos
Herencia
Del tema anterior
Persistente
Entre objetos
Asociacin
Todo-Parte
Entre clases
No persist.
C1
C2
Uso (depend)
C1
C2
Agregacin
Composicin
Generalizacin
vehiculo areo
avion
helicoptero
HERENCIA
Motivacin
Florista
Panadero
cobrar()
cobrar()
darRecibo()
darRecibo()
Asociamos ese
comportamiento
a una categora
general
(generalizacin)
Vendedor
coches
....
cobrar()
darRecibo()
Dependiente
cobrar()
darRecibo()
Clasificacin y generalizacin
HERENCIA
Definicin
HERENCIA
Test ES-UN
Un pjaro es un animal
Un gato es un mamfero
Un pastel de manzana es un pastel
Una matriz de enteros es un matriz
Un coche es un vehculo
HERENCIA
Test ES-UN
Un pjaro es un mamfero
Un pastel de manzana es una manzana
Una matriz de enteros es un entero
Un motor es un vehculo
10
HERENCIA
Principales usos
Tipos de Herencia
Simple/Mltiple
De implementacin/de interfaz
12
Tipos de Herencia
Simple/Mltiple
13
Tipos de Herencia
De implementacin/de interfaz
14
Herencia
Caracterizacin semntica
Atributos de la generalizacin
Solapada/Disjunta
Completa/Incompleta
Esttica/Dinmica
16
Herencia
Caracterizacin: ejemplos
17
HERENCIA DE IMPLEMENTACIN
Herencia Simple
19
int main() {
Circulo c;
c.setColor(AZUL);
c.getColor();
c.vaciarCirculo();
...
}
20
Herencia en C++
Visibilidad atributos/mtodos
class Figura2D {
protected:
Color colorRelleno;
...
};
int main () {
Circulo c;
c.colorRelleno=NINGUNO;
// ERROR! colorRelleno
// es privado aqu
}
Herencia Protegida
class Circulo : protected Figura2D {
...
};
<<public>>
<<protected>>
Herencia Privada
class Circulo : private Figura2D {
...
};
<<private>>
22
CD
H. Protegida
CD
H. privada
Private
No direct.
accesible
No direct.
accesible
No direct.
accesible
Protected
Protected
Protected
Private
Public
Public
Protected
Private
mbito
Herencia
Visibilidad
en clase base
Abuela
+ publico: int
# protegido: int
- privado: int
+ setPublicoAbuela(int)
+ setProtegidoAbuela(int)
+ setPrivadoAbuela(int)
+ inicializaTodoAUno();
<<??>>
+inicializaTodoAUno()
<<public>>
Implementa el mtodo
Hija::inicializaTodoAUno() suponiendo
que la herencia entre Abuela y Padre es:
Hija
Pblica
Protegida
Privada
+inicializaTodoAUno()
24
Herencia Simple
26
Los constructores no
se heredan
27
A
B
C
28
29
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 implcita a Figura2D()
Circulo(Color col, double r) : Figura2D(col), radio(r) {}
Circulo(const Circulo& cir)
: Figura2D(cir), radio(cir.radio) {}
...};
30
El destructor no se
hereda.
A
B
C
32
Construccion/destruccin en resumen
33
titular: string
saldo: double
interes: double
numCuentas: int
+
+
+
+
+
+
+
+
+
+
+
TCuenta()
TCuenta(const TCuenta &)
operator=(const Tcuenta &) : TCuenta&
~TCuenta()
getTitular() : string
getSaldo() : double
getInteres() : double
setSaldo(double) : void
setInteres(double) : void
abonarInteresMensual() : void
mostrar() : void
34
35
36
37
TCuentaJoven
- int edad
+
+
+
+
+
+
+
+
TCuentaJoven()
TCuentaJoven(const TCuentaJoven&)
~TCuentaJoven()
operator=(const TCuentaJoven&) : TCuenta&
abonarInteresMensual() : void
getEdad() : int
setEdad(int) : void
mostrar() : void
38
Reemplazo
Mtodos
aadidos
Mtodo
Refinado
40
Herencia Simple
Upcasting
Convertir un objeto de tipo derivado a tipo base
TCuentaJoven tcj;
cout << (TCuenta)tcj << endl;
cout << TCuenta(tcj) << endl;
TCuenta tc;
tc = tcj; // upcasting implcito
cout << tc << endl;
42
TCuenta
TCuentaJoven
43
TCuenta
TCuentaJoven
(objeto)
tc
tc->getEdad();
// ERROR
POR QU??
44
HERENCIA DE IMPLEMENTACIN
Herencia Mltiple
TCuenta
TEmpresa
};
TCuentaEmpresarial
Cmo implementar TCuentaEmpresarial?
50
51
TCuenta
TEmpresa
(1)
Clase Abuela
TCuentaEmpresarial
Clase Madre1
(2)
Clase Madre2
Clase Hija
Qu problemas pueden darse en (1)? Y en (2)?
52
{ string n;
if
n= TCuenta::getNombre();
else
n= TEmpresa::getNombre();
}
};
53
}
class Madre_2: virtual public Abuela{
}
class Hija: public Madre_1, public Madre_2 {
HERENCIA DE INTERFAZ
Herencia de interfaz
57
Herencia de interfaz
A* obj =
new B();
obj->x(); // OK
obj->y(); // ERROR
58
El principio de sustitucin
Debe ser posible utilizar cualquier objeto
instancia de una subclase en el lugar de
cualquier objeto instancia de su superclase sin
que la semntica del programa escrito en los
trminos de la superclase se vea afectado.
(Liskov, 1987)
Subtipo: Una clase B, subclase de A, es un subtipo de A si
podemos sustituir instancias de A por instancias de B en
cualquier situacin y sin ningn efecto observable.
El principio de sustitucin
funcion medir(objeto) {
si (objeto <= 5)
sino si (objeto == 0)
...}
El principio de sustitucin
class
class Dependiente
Dependiente {{
public:
public:
int
int cobrar();
cobrar();
void
void darRecibo();
darRecibo();
...};
...};
class
class Panadero
Panadero
:: public
public Dependiente
Dependiente
{...}
{...}
Panadero
Panadero p;
p;
Dependiente&
Dependiente& d1=p;
d1=p; //
// sustit.
sustit.
Dependiente*
d2=&p;
//
Dependiente* d2=&p; // sustit.
sustit.
Dependiente
d3=p;
Dependiente d3=p;
//
// NO
NO sustit.:
sustit.: object
object slicing
slicing
Java: directamente
class
class Dependiente
Dependiente {{
public
public int
int cobrar();
cobrar();
public
void
public void darRecibo();
darRecibo();
...};
...};
class
class Panadero
Panadero
extends
extends Dependiente
Dependiente
{...}
{...}
Panadero
Panadero pp == new
new Panadero();
Panadero();
Dependiente
d1=p;
Dependiente d1=p; //
// sustit.
sustit.
HERENCIA DE INTERFAZ
Objetivos:
HERENCIA DE INTERFAZ
Tiempo de enlace
Ventaja: FLEXIBILIDAD
HERENCIA DE INTERFAZ
Tiempo de enlace
HERENCIA DE INTERFAZ
Tiempo de enlace
HERENCIA DE INTERFAZ
Mtodos virtuales
TCuenta*
TCuenta* tc
tc == new
new TCuentaJoven;
TCuentaJoven;
tc->abonarInteresMensual();
tc->abonarInteresMensual();
//
// Enlace
Enlace dinmico:
dinmico: TCuentaJoven::abonarInteresMensual()
TCuentaJoven::abonarInteresMensual()
HERENCIA DE INTERFAZ
Mtodos virtuales
class
class TCuenta
TCuenta {{
...
...
virtual
virtual void
void abonarInteresMensual();
abonarInteresMensual();
};
};
TCuenta* tc = new TCuentaJoven;
delete tc; // Qu destructor se invoca? ~TCuenta()
Queremos destruir el objeto de tipo TcuentaJoven a travs de un puntero a Tcuenta
Necesitamos que el destructor de la clase base tenga enlace dinmico.
class
class TCuenta
TCuenta {{
...
...
virtual
virtual ~TCuenta();
~TCuenta();
};
};
delete tc; // Qu destructor se invoca? ~TCuentaJoven()
HERENCIA DE INTERFAZ
Mtodos virtuales
y el principio de sustitucin
class
class TCuenta
TCuenta {{
...
...
virtual
virtual void
void abonarInteresMensual();
abonarInteresMensual();
virtual
virtual ~TCuentaVirtual();
~TCuentaVirtual();
}}
HERENCIA DE INTERFAZ
Clases abstractas
HERENCIA DE INTERFAZ
Clases abstractas
HERENCIA DE INTERFAZ
Notacin UML para clases abstractas
CLASE ABSTRACTA
Vehculo
CLASE ABSTRACTA
CLASE ABSTRACTA
Areo
Terrestre
{abstract}
Coche
Bicicleta
Avin
CLASES CONCRETAS
Helicptero
HERENCIA DE INTERFAZ
Clase derivada
class
class Circulo
Circulo :: public
public Forma
Forma
{{
int
int radio;
radio;
public:
public:
void
void dibujar()
dibujar() {...};
{...};
...
...
}}
HERENCIA DE INTERFAZ
abstract
abstract class
class Forma
Forma
{{
private
private int
int posx,
posx, posy;
posy;
public
abstract
void
public abstract void dibujar();
dibujar();
public
int
getPosicionX()
public int getPosicionX()
{{ return
return posx;
posx; }}
...
...
}}
Clase derivada
class
class Circulo
Circulo extends
extends Forma
Forma {{
private
private int
int radio;
radio;
public
void
dibujar()
public void dibujar()
{...};
{...};
...
...
}}
HERENCIA DE INTERFAZ
Interfaces
HERENCIA DE INTERFAZ
Notacin UML para interfaces
<<interface>>
Vehculo
INTERFAZ
CLASE ABSTRACTA
CLASE ABSTRACTA
Areo
Terrestre
{abstract}
Coche
Bicicleta
Avin
CLASES CONCRETAS
Helicptero
HERENCIA DE INTERFAZ
Interfaces en Java
interface
interface Forma
Forma
{{
//
// -- Sin
Sin atributos
atributos de
de instancia
instancia
//
Slo
constantes
estticas
// - Slo constantes estticas
//
// -- Todos
Todos los
los mtodos
mtodos son
son abstractos
abstractos por
por definicin
definicin
void
dibujar();
void dibujar();
int
int getPosicionX();
getPosicionX();
...
...
}}
class
class Circulo
Circulo implements
implements Forma
Forma
{{
private
private int
int posx,
posx, posy;
posy;
private
int
radio;
private int radio;
public
public void
void dibujar()
dibujar()
{...};
{...};
public
public int
int getPosicionX()
getPosicionX()
{...};
{...};
}}
HERENCIA DE INTERFAZ
Interfaces en C++
class Forma
class Forma
{
{
// - Sin atributos de instancia
// - Sin atributos de instancia
// - Slo constantes estticas
// - Slo constantes estticas
// - Todos los mtodos se declaran abstractos
// - Todos los mtodos se declaran abstractos
public:
public:
virtual void dibujar()=0;
virtual void dibujar()=0;
virtual int getPosicionX()=0;
virtual int getPosicionX()=0;
// resto de mtodos virtuales puros...
// resto de mtodos virtuales puros...
}
}
class
class Circulo
Circulo :: public
public Forma
Forma //
// Herencia
Herencia pblica
pblica
{{
private:
private:
int
int posx,
posx, posy;
posy;
int
radio;
int radio;
public:
public:
void
void dibujar()
dibujar() {...}
{...}
int
getPosicionX()
int getPosicionX() {...};
{...};
}}
HERENCIA DE INTERFAZ
<<interface>>
Comparable
compareTo(Comparable) : int
class
class Entero
Entero implements
implements Comparable
Comparable {{
private
private int
int n;
n;
Entero(int
Entero(int i)
i) {{ n=i;
n=i; }}
Entero
compareTo(Comparable) : int
...
}}
public
public int
int compareTo(Comparable
compareTo(Comparable e)
e) {{
Entero
Entero e2=(Entero)e;
e2=(Entero)e;
if
(e2.n
if (e2.n >> n)
n) return
return -1;
-1;
else
if
(e2.n
==
n)
return
else if (e2.n == n) return 0;
0;
return
1;
return 1;
}}
HERENCIA DE INTERFAZ
nombre
saldo
inters
numCuentas
TCuentaAbstracta
TCuentaJoven
edad: int
+ TCuentaAbstracta()
+ TCuentaAbstracta(TCuentaAbstracta)
+ ~TCuenta()
+ getNombre() const
+ getSaldo() const
+ getInteres() const
+ setSaldo()
+ setInteres()
+abonarInteresMensual(): void
+mostrar()
<<friend>> operator<<(...)
+ TCuentaJoven()
+ TCuentaJoven(TCuentaJoven)
+ ~TCuentaJoven()
+ getEdad(): int
+ setEdad(int): void
+abonarInteresMensual(): void
+mostrar()
<<friend>> operator<<(...)
HERENCIA DE INTERFAZ
class
class TCuentaAbstracta
TCuentaAbstracta {{
protected:
protected:
...
...
public:
public:
...
...
virtual
virtual void
void abonarInteresMensual()=0;
abonarInteresMensual()=0;
};
};
class
class TCuentaJoven:
TCuentaJoven: public
public TCuentaAbstracta
TCuentaAbstracta {{
private:
private:
int
int edad;
edad;
public:
public:
...
...
//
// IMPLEMENTACION
IMPLEMENTACION en
en clase
clase derivada
derivada
void
abonarInteresMensual(){
void abonarInteresMensual(){
//no
//no inters
inters si
si el
el saldo
saldo es
es inferior
inferior al
al lmite
lmite
if
(getSaldo()>=10000){
if (getSaldo()>=10000){
setSaldo(getSaldo()*(1+getInteres()/12/100));
setSaldo(getSaldo()*(1+getInteres()/12/100));
}}
};
};
//
sigue...
// sigue...
HERENCIA DE INTERFAZ
Upcasting a clase abstracta?
TCuentaJoven
TCuentaJoven tcj;
tcj;
TCuenta
TCuenta tc
tc == (TCuenta)tcj;
(TCuenta)tcj; ??
TCuenta*
TCuenta* ptc
ptc == (TCuenta
(TCuenta *)
*) &tcj;
&tcj; ??
TCuenta&
TCuenta& rtc
rtc == (Tcuenta
(Tcuenta &)
&) tcj;
tcj; ??
TCuentaJoven
TCuentaJoven tcj;
tcj;
TCuenta*
TCuenta* ptc
ptc == &tcj;
&tcj;
TCuenta&
TCuenta& rtc
rtc == tcj;
tcj;
TFijo
double sueldo
+
+
+
+
TFijo()
TFijo(TFijo &)
~TFijo()
setSueldo()
TComisionista
double base, comisin, ventas;
+ TComisionista()
+ TComisionista(TComisionista &)
+ ~TComisionista()
+ setComisin()
+ getComisin() const
+ setBase()
+ getBase() const
int
int main(){
main(){
int
int tipo;
tipo;
Empleado
Empleado *eptr;
*eptr;
cout<<Introduce
cout<<Introduce tipo<<endl;
tipo<<endl;
cin>>tipo;
//1:fijo,
cin>>tipo; //1:fijo, 22 comisionista
comisionista
switch
(tipo){
switch (tipo){
case
case 1:
1: eptr=new
eptr=new Fijo();
Fijo();
break;
break;
case
case 2:eptr=new
2:eptr=new Comisionista();
Comisionista();
break;
break;
}}
eptr->getSalario();
eptr->getSalario();
delete
delete eptr;
eptr;
}}
HERENCIA DE IMPLEMENTACIN
Uso seguro
Herencia de implementacin
80
Constreir restricciones
Extender funcionalidad
81
Especializacin
OK!
VentanaDeTexto
editar()
82
Especificacin
OK!
PilaDeEnteros
{abstract}
apila(Object) : void
apila(Object) : void
desapila() : Object
desapila() : Object
tope() : Object
tope() : Object
83
Restriccin (limitacin)
Pjaro
Volar()
Pingino
Nadar()
Generalizacin
Ventana
Coordenada_x
Coordenada_y
Mover()
VentanaColor
colorFG
Se extiende el comportamiento
de la clase base para obtener un
tipo de objeto ms general.
Usual cuando no se puede
modificar la clase base. Mejor
invertir la jerarqua.
colorBG
setColorFG()
getColorFG()
85
La implementacin se parece
pero semnticamente los
conceptos no estn relacionados
jerrquicamente (test es-un).
INCORRECTA!!!!
Lnea
direccion
setDireccion()
86
Herencia de Construccin
Pila
elementoAt(int i) : Object
apila(Object) : void
capacidad() : int
desapila() : Object
numElementos() : int
tope() : Object
87
Array
Pila
elementoAt(int i) : Object
apila(Object) : void
capacidad() : int
numElementos() : int
<<private>>
desapila() : Object
tope() : Object
88
HERENCIA
Beneficios y costes de la herencia
Beneficios de la Herencia
Reusabilidad software
Comparticin de cdigo
Consistencia de interface
Construccin de componentes
Prototipado rpido
Polimorfismo
Ocultacin de informacin
[BUDD] 8.8
90
Costes de la Herencia
Velocidad de ejecucin
Tamao del programa
Sobrecarga de paso de mensajes
Complejidad del programa
[BUDD] 8.9
91
HERENCIA
Eleccin de tcnica de reuso
Herencia vs Todo-Parte
93
Herencia vs Todo-Parte
Regla del cambio: no se debe usar herencia para describir una
relacin IS-A si se prev que los componentes puedan cambiar en
tiempo de ejecucin (si preveo que pueda cambiar mi vocacin ).
94
class coche
{...
private:
Motor m;
};
}
95
};
97
98
Con herencia una clase nueva puede ser declarada como una subclase
de una clase existente, lo que provoca que todas las reas de datos y
funciones asociadas con la clase original se asocien automticamente
con la nueva abstraccin de datos.
class Conjunto : public Lista{
public:
Conjunto() : Lista() {};
//un conjunto no puede contener valores repetidos
void add (int el){ //refinamiento
if (!includes(el)) Lista::add(el);
};
};
99
En realidad deberamos:
Usar herencia privada
Reescribir todos los mtodos de Conjunto
basndo su implementacin en los de Lista.
100
101
Desventajas