You are on page 1of 57

Programación III

Herencia en Java - Curso 2015-2016

Depto. de Informática y Automática


Grado en Ingeniería Informática
1 Dr. J.R. García-Bermejo Giner
• La herencia es un mecanismo nuevo, propio
de la programación orientada a objetos.

• Consiste en crear una clase nueva tomando


como punto de partida otra clase ya
existente.

• La nueva clase “hereda” todos los atributos


y métodos de la clase base, respetando los
modificadores de acceso (private,
protected).

2
Competencias Teóricas

• Comprender el uso del mecanismo de Herencia como


método para facilitar la reutilización de código
• Comprender el concepto de derivación por herencia.
• Comprender el concepto de clases y métodos
abstractos
• Comprender el concepto de interface

3
Competencias prácticas

• Crear clases derivadas por herencia


• Redefinir métodos heredados
• Emplear el ascenso por la jerarquía de herencia
• Utilizar clases y métodos abstractos
• Definir y utilizar interfaces

4
Reutilización de código

Cuando un programa modela varios objetos de un cierto dominio de


problema, es frecuente hallar clases que comparten atributos y
métodos; de hecho son los mismos atributos y métodos en distintas
clases. Esto supone problemas cuando hay que modificar el programa,
puesto que requiere modificar más de una vez el mismo atributo y el
mismo código.

5
Reutilización de código

Una buena solución consiste en “sacar factor común”, esto es,


concentrar en una sola clase todos los atributos y métodos comunes,
creando después otras clases por herencia. Esas clases siguen heredan
las partes comunes, y añaden y/o redefinen métodos para adaptarlos a
sus propias necesidades.

Esto es un proceso de ABSTRACCIÓN (de lo más concreto a lo más


general, de clases muy particulares a clases muy generales, que actúan
como base de la jerarquía de herencia).

6
Empleados, Comerciales y
Administrativos
En una empresa hay empleados, algunos de los cuales son comerciales,
otros administrativos, etc. Todos los empleados tienen un nombre y un
departamento, pero los comerciales tienen además unas ventas y unos
porcentajes; los administrativos están asociados a un Servicio, etc.

El mecanismo de herencia permite modelar esto de manera muy


eficiente, creando jerarquías de herencia en que las clases derivadas (las
herederas) tienen una relación del tipo “es_un” con las clases base (de
las que heredan). Por ejemplo, un Comercial “es_un” Empleado. Es
una relación de herencia.

No hay que confundir la relación de herencia con la de composición.


Por ejemplo, todo Empleado “tiene_un” nombre, “tiene_un”
departamento, etc.
7
Derivación por herencia
El proyecto siguiente, SintaxisDeLaHerenciaEnJava, muestra la
forma en que se deriva una clase (Comercial) de otra clase
(Empleado).

Para derivar por herencia una clase, se emplea la palabra reservada


extends que denota que la clase de su derecha se deriva de la clase
de su izquierda:

class Derivada extends ClaseBase {

8
Derivación por herencia
class Derivada extends ClaseBase {

La clase Comercial hereda todas las características de empleado,


esto es, todo ejemplar de Comercial tiene nombre y
departamento, procedentes de Empleado.

Además, la clase Comercial tiene atributos adicionales (ventas),


que la distinguen de Empleado.

Todo esto se ve con más claridad en el diagrama siguiente.

9
Diagrama

10
DEMO
Proyecto: SintaxisDeLaHerenciaEnJava

11
Observaciones

• En la clase derivada se pueden añadir atributos


(ventas).
• En la clase derivada se pueden añadir métodos
(getVentas() y setVentas()).
• En la clase derivada se pueden redefinir métodos
(imprimir())

12
Observaciones

• El método imprimir() de Comercial redefine


el método imprimir() de Empleado.
• Además, el método imprimir() de Comercial
hace uso del método imprimir() de Empleado.
Si se añaden atributos a Empleado, no será preciso
modificar el método de Comercial, puesto que el
método imprimir() de empleado ya mostrará
esos atributos.

13
Observaciones
• Los ctores de Comercial invocan explícitamente a
los ctores de Empleado, empleando la sintaxis :
super(arg_1, arg_2).
• Obsérvese que el constructor de Empleado que se
invoca depende del tipo de los argumentos.
• En todos los casos se da valor a las ventas mediante
setVentas(). Esto hace posible validar el valor de
ventas, impidiendo que un ctor pueda darle un valor
negativo. Obsérvese que este método puede lanzar
una excepción, que se captura en main().

14
Observaciones
• Por comodidad y seguridad, lo más frecuente es
declarar public únicamente los servicios que deben
quedar al alcance de otras; los atributos (y los
servicios privados) se declaran private.
• Puede ser interesante asignar el modificador de
acceso protected a ciertas características de la
clase base si se desea limitar el acceso a un servicio a
las clases relacionadas por herencia con una cierta
clase base, sin ofrecerlo a otras clases.

15
Observaciones

La clase derivada hereda todos los atributos de la clase base,


siempre que el modificador de acceso de esos atributos sea
public. Si el modificador de acceso es private o protected,
hay limitaciones de acceso (ver cuadro).

16
Uso de public, protected y private
Especificador de acceso de la
Tipo de herencia
característica de la clase base
public en la clase derivada
public

Se puede acceder directamente a la característica desde


los métodos de la clase derivada.
protected en la clase derivada
protected

Se puede acceder directamente a la característica desde


los métodos de la clase derivada. Al ser protected,no
es visible fuera de la clase derivada, aunque si en el
mismo paquete.
oculta (invisible) en la clase derivada
private

Se puede acceder a la característica desde los métodos


de la clase derivada, empleando métodos public o
protected de la clase base.
17
Observaciones

El ctor de la clase derivada invoca al ctor de la clase base de


forma implícita (si no se dice nada) o de forma explícita (si se
escribe super con los argumentos necesarios).

18
Otros ejemplos

Véanse también los proyectos siguientes:


1. Empleado_a_comisionJava
2. Empleado_con_sueldo_mas_comisionJava
3. ConstructoresYHerenciaEnJava

19
Observaciones
Los dos primeros proyectos resuelven de otra forma el problema de un
Empleado, suponiendo en el primer caso que trabaja a comisión, y en
el segundo que trabaja a sueldo mas comisión.

Los proyectos son independientes, y no hacen uso de herencia, lo cual


da lugar a una notable duplicidad en el código.

El tercer proyecto (constructores y herencia en Java) muestra el orden


de ejecución de constructores en Java, mucho más sencillo que el de C
++, por cuanto no existen las dos pilas independientes (una para
constructores y otra para destructores) propias de C++-

20
DEMO
Proyecto: Empleado_A_Comision_Java

21
DEMO
Proyecto: Empleado_A_Sueldo_Mas_Comision_Java

22
DEMO
Proyecto: ConstructoresYHerenciaEnJava

23
Herencia y descriptores
El uso de punteros para acceder a clases relacionadas por herencia
cumple dos reglas relativamente sencillas:
Se puede asignar la dirección de un ejemplar de clase
DERIVADA a cualquier puntero de una clase PREDECESORA
(porque la clase derivada “es_un” ejemplar de la predecesora,
todo Coche “es_un” Vehiculo).
No se puede asignar la dirección de un ejemplar de clase
PREDECESORA a un puntero de alguna clase DERIVADA (no es
cierto que todo Vehiculo “es_un” Coche).

Véase el proyecto PunterosYHerenciaJava como


ejemplo.

24
Diagrama

25
DEMO
Proyecto: PunterosYHerenciaEnJava

26
PunterosYHerenciaJava

System.out.println("Caso de un pD que apunta a una ClaseDerivadaDerivadaDerivada:");


// Se puede acceder al método de la clase base y de la clase derivada
pD.metodo_clase_base();
pD.metodo_clase_derivada();

System.out.println("Caso de un pDD que apunta a una ClaseDerivadaDerivadaDerivada:");


pDD.metodo_clase_base();
pDD.metodo_clase_derivada();
pDD.metodo_clase_derivada_derivada();

pDDD.metodo_clase_base();
pDDD.metodo_clase_derivada();
pDDD.metodo_clase_derivada_derivada();
pDDD.metodod_clase_derivada_derivada_derivada();

}
}

27
PunterosYHerenciaJava
run:
Caso de un pBase que apunta a una ClaseDerivadaDerivadaDerivada:

Este es el método de la clase base

Caso de un pD que apunta a una ClaseDerivadaDerivadaDerivada:

Este es el método de la clase base


Este es el método de la clase derivada

Caso de un pDD que apunta a una ClaseDerivadaDerivadaDerivada:

Este es el método de la clase base


Este es el método de la clase derivada
Este es el método de la clase derivada derivada

Caso de un pDD que apunta a una ClaseDerivadaDerivadaDerivada:

Este es el método de la clase base


Este es el método de la clase derivada
Este es el método de la clase derivada derivada
Este es el método de la clase derivada derivada derivada

28
Métodos redefinidos
• Aunque no se conozca de antemano la
existencia de una clase derivada, que se creará
en el futuro, basta asignar la dirección de un
objeto de la clase DERIVADA a un puntero de
la clase BASE para que el entorno busque y
ejecute el método virtual (abstracto, en Java) de
la clase DERIVADA.
• Es como un switch() basado en el TIPO.
29
Métodos abstractos
• Cuando un método carece de cuerpo, esto es, cuando un
método tiene como cuerpo un “;” se dice que el método es
abstracto.
• Todo clase que posea un método abstracto se denomina
abstracta, y no se pueden crear ejemplares de esa clase (no se
puede instanciar).
• Es posible crear descriptores de una clase abstracta.
• Es posible crear una clase derivada por herencia de una clase
abstracta. Si la clase derivada implementa todos los métodos
abstractos de la clase base, pasa a ser concreta y se puede
instanciar. Si no los implementa, también es abstracta.

30
Métodos abstractos

• Toda clase abstracta debe marcarse con el modificador


“abstract”
• Todo método abstracto tiene que marcarse con el modificador
“abstract”.

31
Métodos abstractos

Como ejemplo, véase el ejemplo MetodosAbstractosJava.

32
Diagrama

33
DEMO
Proyecto: MetodosAbstractosJava

34
interfaces en Java
• Considérese una clase tal que:
• Todos sus atributos son constantes, con los modificadores
public static final (se pueden omitir los
modificadores, el compilador los añade efectivamente).
• Todos sus métodos son abstractos, con los modificadores
public abstract (se pueden omitir los
modificadores, el compilador los añade efectivamente).
• Esto es una interface.

35
El tipo interface de Java
public interface Nombre [extends Interfaz1, Interfaz2,...InterfazQ]{
[public static final] tipo1 atributo1 = valor1;
...
[public static final] tipoM atributoN = valorP;
[public abstract] tipo nombreMetodo(argumentos);
...
[public abstract] tipo nombreMetodo(argumentos);
}

Véase un ejemplo real de interfaz.

36
El tipo interface de Java
public interface DataBase{
void loadFrom(File f);
void saveTo(File f);
void exportTo(String destino);
void importFrom(String origen);
void add(String registro);
void remove(String registro);
void edit(String registro);
String[] report(String[] criterios);
}

• Esta interfaz debe ser implementada por una clase, que definirá todos sus
métodos. 37
El tipo interface de Java
public interface DataBase<T>{
void loadFrom(File f);
void saveTo(File f);
void exportTo(String destino);
void importFrom(String origen);
void add(T registro);
void remove(T registro);
void edit(T registro);
T[] report(String[] test);
}

Las interfaces, como las clases y los métodos, son parametrizables (se pueden crear plantillas,
como esta).
38
El tipo interface de Java
Para indicar que una clase implementa o satisface una interface se utiliza la palabra
reservada implements

public class StringDB implements DataBase<String> {


public void exportTo(String destination)
{ ... }
public void importFrom(String origen)
{ ... }
public void remove(String registro)
{ ... }
public void edit(String registro)
{ ... }
public String[] report(String[] criterios)
{ ... }
} TA Martes 2
39
Interfaces

Como ejemplo, véase el proyecto EjemploInterfazJava.

40
Diagrama

41
DEMO
Proyecto: EjemploInterfazJava

42
interfaces y herencia
“múltiple” en Java
• En Java no hay herencia múltiple, pero una interface o una clase
pueden heredar de tantas interfaces como se desee. El resultado
va a ser similar al de la herencia múltiple; se indica que la interfaz
se deriva de otra u otras interfaces empleando la palabra
reservada extends propia de la herencia.

public interface X extends Y, Z, T {


...
}
donde Y, Z y T son interfaces.

43
interfaces y herencia
“múltiple” en Java

Véase el proyecto HerenciaMultipleJava.

44
Diagrama

45
DEMO
Proyecto: HerenciaMultipleJava

46
interfaces y herencia
“múltiple” en Java
Notas
La clase BaseDatosConArchivos implementa las interfaces
ImportExport y ReadWrite, no hereda de ellas (no son
clases).
La clase BaseDatosConArchivos necesita aportar una
implementación para todos los métodos especificados en las
interfaces ImportExport y ReadWrite. De no se así, se
producirá un error de compilación.

47
Las interfaces como tipos
• No se pueden crear ejemplares de una interfaz, pero se pueden
crear descriptores de ese tipo, puesto que las interfaces son
tipos.
• Los descriptores de tipo interfaz admiten como valor:
• Descriptores de interfaces derivadas.
• Clases que implementen esa interfaz, u otra derivada.
Es posible usar descriptores de un tipo de interfaz para ejecutar
métodos de clases que implementen esa interfaz. Se respeta el
mecanismo de herencia exactamente igual que si fueran
descriptores de clases (a fin de cuentas, son descriptores de clases
que implementan esa interfaz).
48
Las interfaces como tipos
El tipo de la clase cuyo descriptor se almacena en un descriptor de
interfaz determina el método ejecutado, siempre que éste se haya
redefinido en la clase.

Por tanto, se puede cambiar la clase almacenada en ese descriptor


y el resultado será cambiar por completo la implementación.

Esto tiene consecuencias muy interesantes, puesto que permite


diseñar siempre con INTERFACES, o clases abstractas, y relegar la
implementación, que finalmente se hará del modo más eficiente
posible.
49
Las interfaces como tipos
En el tema dedicado a Colecciones se estudia una interfaz muy
importante, List<T>. Lo posibilidad de cambiar una interfaz por
otra se refleja en el código siguiente:

List<String> lista = new ArrayList<String>();


...
lista = new LinkedList<String();

Es posible almacenar en lista el descriptor de cualquier colección que


implemente la interface List<T>. Esto tiene consecuencias
importantes sobre el rendimiento de la aplicación, SIN MODIFICAR
más código que el que define la implementación utilizada
(ArrayList o LinkedList, por 50
ejemplo).
Las interfaces como tipos

Véase el proyecto InterfacesComoTipos. (No se repiten


Publicación, Libro y Revista, que ya se conocen).

51
52
DEMO
Proyecto: InterfacesComoTipos

53
Las interfaces como tipos
Notas
El método lanzarImpresion() se ha construido empleando
como argumento un descriptor de Publicacion, y por tanto
admitirá cualquier clase que implemente esa interfaz. Por tanto, si
en un futuro se crea algún otro tipo de publicación (Periódico
implements Publicacion, pej), sería factible escribir
ict.lanzarImpresion(periodico). Obsérvese que
imprimir es abstracto y puede y debe ser implementado,
adaptándolo a la situación.
También se podría hacer que el argumento de lanzarImpresion
fuera una clase abstracta, fijando así la secuencia de métodos
invocados por imprimir.
54
Las interfaces como tipos

Este comportamiento va a tener mucha importancia en el tema


dedicado a colecciones. En efecto, la biblioteca de colecciones de
Java tiene una clase base que es la raíz de una extensa jerarquía
de interfaces. Estas interfaces poseen diferentes
implementaciones, con características diferentes, que se usan en
uno otro momento en función de las necesidades de nuestra
aplicación.

55
Las interfaces como tipos

Los programas basados en colecciones suelen hacer uso de


interfaces como tipos, esto es, declarar variables cuyo tipo es
alguna interfaz de la jerarquía de colecciones. El propósito de
utilizar estas variables es hacer posible cambiar la implementación
utilizada de esa interfaz, sin modificar para nada el resto del
programa, y obteniendo los beneficios derivados de la nueva
implementación seleccionada

56
Programación III
Herencia en Java - Curso 2015-2016

Depto. de Informática y Automática


Grado en Ingeniería Informática
57 Dr. J.R. García-Bermejo Giner

You might also like