Documente Academic
Documente Profesional
Documente Cultură
5
HERENCIA
Cristina Cachero, Pedro J. Ponce de Len
versin 20111015
Tema 3. HERENCIA
Objetivos
Herencia
Del tema anterior
Persistente
Entre objetos
Asociacin
Todo-Parte
Entre clases
No persist.
C1
C2
Uso (depend)
C1
Agregacin
Composicin
Generalizacin
vehiculo areo
avion
helicoptero
C2
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
Determina si un objeto puede ser a la vez instancia de dos o ms subclases de ese nivel
de herencia.
Java/C++ no soporta la herencia solapada (tipado fuerte)
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 subcategora de las reflejadas por las clases hijas (incompleta).
Esttica/Dinmica
Determina si un determinado objeto puede pasar de ser instancia de una clase hija a otra
dentro de un mismo nivel de la jerarqua de herencia.
Java/C++ no soporta la herencia dinmica (tipado fuerte)
16
Herencia
Caracterizacin: ejemplos
17
HERENCIA DE IMPLEMENTACIN
Herencia Simple
Herencia Simple
Mediante la herencia, las propiedades definidas en una clase base
son heredadas por la clase derivada.
La clase derivada puede aadir propiedades especficas
(atributos, mtodos o roles)
19
Herencia Simple
class Figura2D {
public void setColor(Color c) {...}
public Color getColor() {...}
private Color colorRelleno;
... }
class Circulo extends Figura2D {
...
public void vaciar() {
colorRelleno=Color.NINGUNO;
// ERROR! colorRelleno es privado
setColor(Color.NINGUNO); // OK
}
}
// cdigo cliente
Circulo c = new Circulo();
c.setColor(AZUL);
c.getColor();
c.vaciarCirculo();
20
Herencia simple
Visibilidad atributos/mtodos
class Figura2D {
protected Color colorRelleno;
...
}
//cdigo cliente
Circulo c;
c.colorRelleno=NINGUNO;
// ERROR! colorRelleno
// es privado aqu
21
Herencia Pblica
<<public>>
22
<<private>>
CD (*)
H. Pblica
CD
H. Protegida
CD
H. privada
Protected
No direct.
accesible
Protected
No direct.
accesible
Protected
No direct.
accesible
Private
Public
Public
Protected
Private
Visibilidad
en clase base
Private
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()
25
Herencia Simple
Herencia Simple
28
Herencia Simple
Los constructores no se
heredan
30
A
B
C
31
32
Ejemplo
class Figura2D {
private Color colorRelleno;
public Figura2D() { colorRelleno= Color.NINGUNO; }
public Figura2D(Color c) { colorRelleno=c; }
public Figura2D(Figura2D f) { colorRelleno=f.colorRelleno; }
...}
class Circulo extends Figura2D {
privste double radio;
public Circulo() { radio=1.0; } //llamada implcita a Figura2D()
public Circulo() { super(); radio=1.0; } //llamada explcita
public Circulo(Color col, double r) { super(col); radio=r; }
public Circulo(Circulo cir) { super(cir); radio=cir.radio; }
...}
33
C++: el destructor no
se hereda.
A
B
C
35
36
Dos estrategias:
Usar mtodos finalize()
Desventaja: No sabemos cundo se ejecutarn.
39
titular: string
saldo: double
interes: double
numCuentas: int
+
+
+
+
+
+
+
+
+
Cuenta()
Cuenta(Cuenta)
getTitular() : string
getSaldo() : double
getInteres() : double
setSaldo(double) : void
setInteres(double) : void
abonarInteresMensual() : void
toString() : String
40
41
42
43
CuentaJoven
- int edad
+
+
+
+
+
+
CuentaJoven()
CuentaJoven(CuentaJoven)
abonarInteresMensual() : void
getEdad() : int
setEdad(int) : void
toString() : String
Reemplazo
Mtodo
Refinado
46
Herencia Simple
Upcasting
Convertir un objeto de tipo derivado a tipo base
CuentaJoven tcj = new CuentaJoven();
Cuenta c;
c = (Cuenta)tcj; // explcito
c = tcj; // implcito
tcj.setEdad(18); //OK
c.setEdad(18); // ERROR!
Un objeto de clase derivada al que se accede a travs de una referencia
a clase base slo se puede manipular usando la interfaz de la clase
base.
47
tcj
TCuenta
TCuentaJoven
48
Cuenta
CuentaJoven
(objeto)
tc
tc.getEdad();
// ERROR
POR QU??
49
Particularidades Herencia
52
HERENCIA DE IMPLEMENTACIN
Herencia Mltiple
Herencia Mltiple
Se da cuando existe ms de una clase base.
C++ soporta la herencia mltiple de implementacin.
Se heredan tanto las interfaces como las implementaciones de
las clases base.
Java slo soporta la herencia mltiple de interfaz.
Slo se hereda la interfaz de las clases base y no la
implementacin.
En esta seccin tratamos la herencia mltiple de implementacin.
55
Cuenta
Empresa
CuentaEmpresarial
Cmo implementar CuentaEmpresarial?
56
57
Cuenta
Empresa
(1)
Clase Abuela
CuentaEmpresarial
Clase Madre1
(2)
Clase Madre2
Clase Hija
Qu problemas pueden darse en (1)? Y en (2)?
58
{ string n;
if
n= Cuenta::getNombre();
else
n= Empresa::getNombre();
}
};
59
}
class Madre_2: virtual public Abuela{
}
class Hija: public Madre_1, public Madre_2 {
HERENCIA DE INTERFAZ
Herencia de interfaz
Objetivos
Separar la interfaz de la implementacin.
Garantizar la sustitucin.
63
Herencia de interfaz
Sustitucin
A obj =
new B();
obj.x(); // OK
obj.y(); // ERROR
64
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
Java: directamente
class
class Dependiente
Dependiente {{
public
public int
int cobrar()
cobrar() {...}
{...}
public
void
darRecibo()
public void darRecibo()
{...}
{...}
...}
...}
class
class Dependiente
Dependiente {{
public:
public:
int
int cobrar();
cobrar();
void
void darRecibo();
darRecibo();
...};
...};
class
class Panadero
Panadero
extends
extends Dependiente
Dependiente
{...}
{...}
class
class Panadero
Panadero
:: public
public Dependiente
Dependiente
{...}
{...}
Panadero
Panadero pp == new
new Panadero();
Panadero();
Dependiente
d1=p;
Dependiente d1=p; //
// sustit.
sustit.
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
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
Enlace dinmico en Java
class Cuenta {
void abonarInteresMensual()
{ setSaldo(getSaldo()*(1+getInteres()/100/12)); }
...}
class CuentaJoven extends Cuenta {
void abonarInteresMensual() { // enlace dinmico por defecto
if (getSaldo()>=10000) super.abonarInteresMensual();
}
...}
HERENCIA DE INTERFAZ
Enlace dinmico en C++
En C++ para que esto sea posible:
class
class Cuenta
Cuenta {{
...
...
virtual
virtual void
void abonarInteresMensual();
abonarInteresMensual();
//
En
C++,
cuando
// En C++, cuando hay
hay herencia,
herencia, es
es aconsejable
aconsejable
//
declarar
siempre
virtual
el
destructor
// declarar siempre virtual el destructor de
de la
la clase
clase
base.
base.
virtual
virtual ~Cuenta();
~Cuenta();
};
};
Cuenta* tc = new CuentaJoven();
tc->abonarInteresMensual();
// Enlace dinmico: CuentaJoven::abonarInteresMensual()
delete tc; // CuentaJoven::~CuentaJoven();
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
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
Clase derivada
class
class Circulo
Circulo :: public
public Forma
Forma
{{
int
int radio;
radio;
public:
public:
void
void dibujar()
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
{{
//
// -- Todos
Todos los
los mtodos
mtodos son
son abstractos
abstractos por
por definicin
definicin
//
Visibilidad
pblica
// - Visibilidad pblica
//
// -- Sin
Sin atributos
atributos de
de instancia,
instancia, slo
slo constantes
constantes estticas
estticas
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()
{...}
{...}
}}
class
class Cuadrado
Cuadrado implements
implements Forma
Forma
{{
private
private int
int posx,
posx, posy;
posy;
private
int
lado;
private int lado;
public
public void
void dibujar()
dibujar()
{...}
{...}
public
public int
int getPosicionX()
getPosicionX()
{...}
{...}
}}
HERENCIA DE INTERFAZ
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;
public
public 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
class
class ParOrdenado
ParOrdenado {{
private
private Comparable[]
Comparable[] par
par == new
new Comparable[2];
Comparable[2];
}}
public
public ParOrdenado(Comparable
ParOrdenado(Comparable p1,
p1, Comparable
Comparable p2)
p2) {{
int
int comp
comp == p1.compareTo(p2);
p1.compareTo(p2);
if
(comp
<=
if (comp <= 0)
0) {{ par[0]
par[0] == p1;
p1; par[1]
par[1] == p2;
p2; }}
else
{{ par[0]
else
par[0] == p2;
p2; par[1]
par[1] == p1;
p1; }}
}}
public
public Comparable
Comparable getMenor()
getMenor() {{ return
return par[0];
par[0]; }}
public
public Comparable
Comparable getMayor()
getMayor() {{ return
return par[1];
par[1]; }}
//
// Codigo
Codigo cliente
cliente
ParOrdenado
ParOrdenado po
po == new
new ParOrdenado(new
ParOrdenado(new Entero(7),
Entero(7), new
new Entero(3));
Entero(3));
po.getMenor();
po.getMenor(); //
// 33
po.getMayor();
po.getMayor(); //
// 77
HERENCIA DE INTERFAZ
interface
interface CanFight
CanFight {{
void
void fight();
fight();
}}
class
class ActionCharacter
ActionCharacter {{
public
public void
void fight()
fight() {}
{}
}}
interface
interface CanSwim
CanSwim {{
void
void swim();
swim();
}}
class
class Hero
Hero extends
extends ActionCharacter
ActionCharacter
implements
CanFight,
implements CanFight, CanSwim,
CanSwim, CanFly
CanFly {{
public
public void
void swim()
swim() {}
{}
public
void
fly()
{}
public void fly() {}
}}
interface
interface CanFly
CanFly {{
void
void fly();
fly();
}}
(tomado de 'Piensa en
Java, 4 ed.', Bruce Eckl)
public
public class
class Adventure
Adventure {{
public
public static
static void
void t(CanFight
t(CanFight x)
x)
{{ x.fight();}
x.fight();}
public
public static
static void
void u(CanSwim
u(CanSwim x)
x)
{{ x.swim();
}
x.swim(); }
public
public static
static void
void main(String[]
main(String[] args)
args) {{
Hero
Hero hh == new
new Hero();
Hero();
t(h);
//
Treat
t(h); // Treat it
it as
as aa CanFight
CanFight
u(h);
//
Treat
it
as
a
CanSwim
u(h); // Treat it as a CanSwim
}}
}}
Fijo
double sueldo
+ Fijo()
+ Fijo(Fijo )
+ setSueldo()
Comisionista
double base, comisin, ventas;
+
+
+
+
+
+
Comisionista()
Comisionista(Comisionista )
setComisin(double) : void
getComisin() : double
setBase(double) : void
getBase() : double
//
// cdigo
cdigo cliente
cliente
int
tipo
int tipo =...;
=...; //1:fijo,
//1:fijo, 22 comisionista
comisionista
Empleado
emp;
Empleado emp;
}}
switch
switch (tipo){
(tipo){
case
case 1:
1:
emp=new
emp=new Fijo();
Fijo();
break;
break;
case
case 2:
2:
emp=new
emp=new Comisionista();
Comisionista();
break;
break;
}}
System.out.println(emp.getSalario());
System.out.println(emp.getSalario());
HERENCIA DE IMPLEMENTACIN
Uso seguro
Herencia de implementacin
86
Constreir restricciones
Extender funcionalidad
87
Especializacin
Ventana
mostrar()
OK!
VentanaDeTexto
editar()
88
Especificacin
OK!
PilaDeEnteros
{abstract}
apila(Object) : void
apila(Object) : void
desapila() : Object
desapila() : Object
tope() : Object
tope() : Object
89
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()
91
La implementacin se parece
pero semnticamente los
conceptos no estn relacionados
jerrquicamente (test es-un).
INCORRECTA!!!!
Lnea
direccion
setDireccion()
92
Herencia de Construccin
Pila
apila(Object) : void
capacidad() : int
desapila() : Object
numElementos() : int
tope() : Object
93
Pila
Array
elementoAt(int i) : Object
capacidad() : int
numElementos() : int
<<private>>
apila(Object) : void
desapila() : Object
tope() : Object
94
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
96
Costes de la Herencia
Velocidad de ejecucin
Tamao del programa
Sobrecarga de paso de mensajes
Complejidad del programa
[BUDD] 8.9
97
HERENCIA
Eleccin de tcnica de reuso
class Coche
{...
private Motor m;
}
}
100
Herencia vs Todo-Parte
Regla del cambio: no se debe usar herencia para describir una relacin ISA si se prev que los componentes puedan cambiar en tiempo de ejecucin
(si preveo que pueda cambiar mi vocacin ).
101
102
103
104
Con herencia, todos los atributos y metodos asociados con la clase base Lista
se asocian automticamente con la nueva clase Conjunto.
class Conjunto extends Lista {
public Conjunto() { super(); }
//un conjunto no puede contener valores repetidos
void add (int el){ //refinamiento
if (!includes(el)) super.add(el);
}
}
105
106
Dejar sin implementar los mtodos que, siendo relevantes para X, no lo son
para la nueva clase C
Reimplementar C utilizando un tipo de datos X distinto sin impacto para los
usuarios de la clase C.
107
Desventajas
108
Bibliografa
138