1. 3. Interfaces
Herencia y clases abstractas
Object y herencia simple
Clases abstractas y métodos genéricos
Fundamento / El por qué
¿Qué son? Definición
Implementación, simple y múltiple
Herencia de Interfaces
Programación III Tema 3 - Interfaces
2. Herencia - Definición
• Relación es-un entre dos clases: coche vehículo,
alumnopersona, rectángulopolígono, etc.
• Clase hija (subclase) clase padre (superclase)
– Hijas - más concretas, padres - comportamiento más general
• En Java, cada hija sólo tiene un padre: herencia simple,
aunque puede tener N hijas
• La raíz de la jerarquía de clases en Java es la clase Object
• Una clases hereda (tiene) todos los métodos y atributos de
sus clases superiores (de la clase hasta Object)
• Sólo puede acceder directamente a los que no sean privados
(private)
• Ventajas principales:
– reutilización de código
– diferenciación de código (menos “if”s)
Programación III Tema 3 - Interfaces
3. Sintaxis
• La relación jerárquica se representa mediante extends
class <hija> extends <padre>
• Ejemplo: Figura
Rectángulo
class Rectangulo extends Figura {
...
}
• La herencia es transitiva: si A B y B C, A C
• Si no hay cláusula extends, la clase deriva de Object
Programación III Tema 3 - Interfaces
4. Ejemplo de herencia
class Persona{
class Alumno extends Persona {
private int edad;
private int curso;
private String nombre;
private char grupo;
private String titulacion;
Persona (int e, String n){
edad = e;
Alumno (int c, char g, String t){
nombre = n;
curso = c;
}
grupo = g;
/* Métodos set/get para todos los
atributos */ titulacion = t;
} }
/* Métodos set/get para todos los
atributos */
Persona }
• Este código da un error ¿por qué?
Alumno
Programación III Tema 3 - Interfaces
5. Llamada de constructores
en herencia 1 - super
• Cuando en una clase no se define ningún
constructor, Java crea (aunque no se ve) el
constructor por defecto
class Persona{
private int edad;
private String nombre;
Persona ( ){ //Constructor por defecto. Existe, pero no se ve.
}
/* Métodos set/get para todos los atributos */
...
public static void main(String args[]){
//Se puede comprobar que existe, creando objetos Persona
Persona p1 = new Persona();
/* La llamada al constructor vacío no da error, porque Java
lo ha creado */
}
}
Programación III Tema 3 - Interfaces
6. Llamada de constructores
en herencia 2 - super
• En el momento en el que el programador crea otro
constructor, el constructor por defecto deja de existir.
class Persona{
private int edad;
private String nombre;
Persona (int e, String n){
edad = e;
nombre = n;
}
/* Métodos set/get para todos los atributos */
...
public static void main(String args[]){
/* Esta misma llamada daría error, porque no existe un constructor
con esas características */
Persona p1 = new Persona();
/*Sí es posible llamar al constructor definido */
Persona p2 = new Persona(20, “Ana”);
}
}
Programación III Tema 3 - Interfaces
7. Llamada de constructores
en herencia 3 - super
• Cuando una clase tiene una
clase padre, lo primero que class Alumno extends Persona {
hace su constructor (aunque no private int curso;
private char grupo;
lo veamos), es llamar al private String titulacion;
constructor de la clase
Alumno(int c, char g, String t){
padre (al constructor vacío: /*Llamada al constructor de la
super( );) clase padre, existe pero no se
ve*/
super();
class Persona{ curso = c;
private int edad; grupo = g;
private String nombre; titulacion = t;
}
}
Persona (int e, String n){
edad = e;
nombre = n; • Este constructor produce un error
} ¿por qué?
/* Métodos set/get para todos los
atributos */
...
}
Programación III Tema 3 - Interfaces
8. Llamada de constructores
en herencia 4 - super
• Solución 1. Crear constructor vacío • Solución 2. Llamar explícitamente al
constructor del padre que sí existe
class Persona{ class Persona{
private int edad; private int edad;
private String nombre; private String nombre;
Persona ( ) { } Persona (int e, String n){
Persona (int e, String n){ edad = e;
edad = e; nombre = n;
nombre = n; }
} }
} class Alumno extends Persona {
class Alumno extends Persona { private int curso;
private int curso; private char grupo;
private char grupo; private String titulacion;
private String titulacion;
Alumno(int c, char g, String t,
Alumno(int c, char g, String t){ int e, String n){
super(); super(e, n);
curso = c; curso = c;
grupo = g; grupo = g;
titulacion = t; titulacion = t;
} }
} }
Programación III Tema 3 - Interfaces
9. Ejemplo de llamada a
constructores
class Figura { class X {
Figura (){ public static void main (...){
s.o.p.(“Creando figura”); Cuadrado c1 = new
} Cuadrado();
} }
}
class Rectangulo extends Figura
{ • ¿Qué sale por pantalla?
Rectangulo (){ • ¿A qué se debe?
s.o.p.(“Creando • (super)
rectangulo”);
}
}
class Cuadrado extends
Rectangulo {
Cuadrado (){
s.o.p.(“Creando cuadrado”);
}
}
Programación III Tema 3 - Interfaces
10. this
• Dentro de un método, hace referencia al objeto
que lo llama
class Persona{
private int edad;
private String nombre;
Persona (int edad, String nombre){
edad = edad;
nombre = nombre;
}
• ¿Qué pasa en este constructor? ¿Cómo resolverlo?
void imprimirDatos(){
s.o.p.(“Persona: “ + this.nombre + “ “ + this.edad);
/* En este caso no sería necesario, es suficiente el
nombre de los atributos */
}
}
Programación III Tema 3 - Interfaces
11. this y super
class Alumno extends Persona{
class Persona{ private int curso;
private int edad; private char grupo;
private String nombre; private String titulacion;
Alumno(int c, char g, String t, int e, String n){
Persona (int edad, String super(e, n);
nombre){ curso = c;
this.edad = edad; grupo = g;
this.nombre = nombre; titulacion = t;
}
void imprimirDatos (){
} s.o.p.(curso + “-” + grupo);
void imprimirDatos(){ s.o.p.(“(“ + titulacion + “)”);
s.o.p.(“Persona: “); }
void imprimirTodos(){
s.o.p.(nombre + “ “);
super.imprimirDatos();
s.o.p.(edad); this.imprimirDatos();
} imprimirDatos();
} }
public static void main(String args[]){
Alumno al;
al = new Alumno(1, 'a', "ITTET", 18, "Pedro");
al.imprimirTodos();
}
}
• ¿Qué obtenemos por pantalla?
Programación III Tema 3 - Interfaces
12. this en constructores
class Alumno extends Persona{
...
Alumno(int c, char g, String t, int e,
String n){
super(e, n);
curso = c;
grupo = g;
titulacion = t;
}
Alumno(int c, char g, String t){
this(c, g, t, 0, “Sin definir”);
}
...
}
Programación III Tema 3 - Interfaces
13. Resumen this y super
– this
• Es la referencia al propio objeto sobre el que se está trabajando.
• No hace falta usarla para acceder a los atributos y métodos propios.
• Pero a veces es necesaria cuando se quiere pasar la referencia al
propio objeto como parámetro de otro método.
• En constructores puede usarse para llamar entre ellos (lo primero)
– super
• Permite referenciar a la clase padre.
• Se emplea cuando se ha redefinido un método y se quiere acceder al
método del padre (si no se usara esta palabra reservada se llamaría
al método de la propia clase y no habría forma de invocar el del
padre). [super.método(...)]
• Permite también llamar al constructor de la clase padre desde el
constructor de la clase hija. [super(...)] Esto es lo primero que se
hace en todo constructor (si no se indica explícitamente, se hace sin
parámetros).
Programación III Tema 3 - Interfaces
14. Comprob. tipo en ejecución
• instanceof
– Permite controlar la clase a la que
pertenece un objeto (no la variable, el
objeto)
Vehiculo[] v = new Vehiculo[3]
v[0] = new Coche();
v[1] = new Moto();
v[2] = new CocheJuguete();
...
if (v[i] instanceof Moto) {
(Moto)v[i] ... }
Programación III Tema 3 - Interfaces
15. Método abstracto
• Precedido de la palabra clave abstract
• Un método abstracto es el que no tiene
implementación
class X {
abstract void m1();
}
• NO es lo mismo que un método “vacío”
class X {
void m1(){ }
}
• Una clase que contiene un método abstracto, es
una clase abstracta, y debe de llevar el modificador
abstract
abstract class X {
abstract void m1();
}
Programación III Tema 3 - Interfaces
16. Herencia de métodos
abstractos
• Cuando una clase hereda un método abstracto, tiene dos
opciones:
– Implementar el método (darle código)
class Y extends X {
void m1(){...}
}
– No implementarlo (no hacer nada con él). En este caso la clase pasa
a ser abstracta (si no se pone abstract no compila)
abstract class Y extends X {
}
• Una clase es abstracta si:
– Tiene un método abstracto definido dentro (clase X)
– Hereda un método abstracto y no lo implementa (clase Y, ejem 2)
• NO se pueden crear objetos de una clase abstracta:
X x1; //Correcto
x1 = new X(); //Incorrecto
¿Por qué?
Programación III Tema 3 - Interfaces
17. Utilidad de métodos
abstractos
• Si no se pueden crear objetos de clases abstractas ¿para qué sirven?
• Son clases de definición
– Indican cómo deben comportarse las subclases, qué métodos deben tener
obligatoriamente (porque la herencia no puede quitar métodos)
– Sirven para proporcionar un comportamiento y definición general a las
subclases, permitiendo especificar en cada subclase una implementación diferente
• No compromete cuál debe ser ese comportamiento
– Puede haber algunos métodos no abstractos porque su código sí pueda definirse
• ej.: FiguraGeometrica – void dibujar() { dibujarArea(); dibujarAristas() }
abstract Animal
abstract void emitirSonido( );
Perro Felino Ave
void emitirSonido( ){ void emitirSonido( ){ void emitirSonido( ){
s.o.p.(“Guau”); s.o.p.(“Grrr...”); s.o.p.(“Pio-pio”);
} } }
Gato Lince Pantera Canario Golondrina
Programación III Tema 3 - Interfaces
18. Modificador final
• final
– Indica que la definición de la clase está completa.
• No se puede heredar de esa clase (no puede tener
subclases).
• Si una clase es declarada abstract y final Error de
compilación
– Otros usos de final :
• en atributos indica constantes (su valor no puede cambiar)
• en métodos indica que no se pueden redefinir en subclases
(una clase final hace a todos sus métodos finales)
Programación III Tema 3 - Interfaces
20. Ordenación de fechas
public class OrdenarFechas {
static void ordenaArray( Fecha v[] )
// Ordena array de fechas por bubble sort
{
for (int i=0; i<v.length-1; i++) {
for (int j=1; j<v.length-i; j++) {
if (v[j-1].esMayorQue(v[j])) {
Fecha temp = v[j];
v[j] = v[j-1]; v[j-1] = temp;
}
}
}
}
...
Programación III Tema 3 - Interfaces
21. Ordenación de fracciones
public class OrdenarFracciones {
static void ordenaArray( Fraccion v[] )
// Ordena array de fracciones por bubble sort
{
for (int i=0; i<v.length-1; i++) {
for (int j=1; j<v.length-i; j++) {
if (v[j-1].esMayorQue(v[j])) {
Fraccion temp = v[j];
v[j] = v[j-1]; v[j-1] = temp;
}
}
}
}
...
Programación III Tema 3 - Interfaces
22. ¿Cómo generalizar?
• Método de ordenación idéntico
– Son clases distintas
– Ambas se pueden comparar por mayor
– Pero no se pueden heredar (no tienen nada que ver)
• ¿Cómo lo generalizamos?
public class OrdenarLoQueSea {
static void ordenaArray( LoQueSea v[] ) {
for (int i=0; i<v.length-1; i++) {
for (int j=1; j<v.length-i; j++) {
if (v[j-1].esMayorQue(v[j])) {
LoQueSea temp = v[j];
v[j] = v[j-1]; v[j-1] = temp;
}
}
} ...
Programación III Tema 3 - Interfaces
23. Solución
interface Ordenable {
boolean esMayorQue( Ordenable o );
}
public class Ordenar {
static void ordenaArray( Ordenable v[] ) {
for (int i=0; i<v.length-1; i++) {
for (int j=1; j<v.length-i; j++) {
if (v[j-1].esMayorQue(v[j])) {
Ordenable temp = v[j];
v[j]=v[j-1]; v[j-1]=temp;
} } } }
class Fraccion implements Ordenable {
public boolean esMayorQue( Ordenable o ) {
if (o instanceof Fraccion) {
Fraccion f2 = (Fraccion) o;
return (1.0*num/den > 1.0*f2.num/f2.den);
} else return false;
...
Programación III Tema 3 - Interfaces
24. El por qué de los interfaces (1)
• Herencia Múltiple
– Una clase tiene más de un padre
– Presenta problemas cuando:
• Se heredan varias implementaciones para un mismo método
• Se heredan varias copias de un mismo atributo
• Ejemplo:
Vehiculo
VehiculoTerrestre VehiculoAcuatico
Coche VehiculoAnfibio Barco
Programación III Tema 3 - Interfaces
25. El por qué de los interfaces
(2)
• Complejidad (Eiffel, C++):
– Si la clase Vehículo tuviera un atributo llamado
matrícula, ¿Cuántas matrículas tendría la clase
VehiculoAnfibio?
– ¿Si Vehículo tuviera un método implementado
de forma diferente por VehiculoTerrestre y por
VehiculoAcuatico?
• Java no permite la herencia múltiple
– ¿Cómo resuelve Java estas jerarquías?
– Mediante otro mecanismo: los interfaces
Programación III Tema 3 - Interfaces
26. ¿Qué es un interface?
• Es un conjunto de métodos
– Sólo cabeceras, sin implementación
– Definen un comportamiento específico para un conjunto
de objetos
• Es una forma de crear tipos (como las clases)
– Se pueden declarar variables
– Se pueden declarar métodos
• Y debido a esto:
– Sus métodos son “abstractos”
– No se pueden instanciar (como las clases abstractas)
– No se hereda codificación, sólo definición
Programación III Tema 3 - Interfaces
27. Definición de interfaces
• Palabra reservada interface seguida de una lista de
métodos (cabeceras) sin implementación
• Ejemplo 1:
interface UnInterface
{
void mensaje1();
void mensaje2();
}
• Ejemplo 2:
interface Driveable
{
boolean startEngine();
void stopEngine();
float accelerate(float acc);
boolean turn(Direction dir);
}
• Todos los métodos de un interface son públicos
Programación III Tema 3 - Interfaces
28. Implementación de interfaces (1)
• Para “implementar” un interface:
– Cláusula implements
– Cuando se relaciona una clase con una interfaz y no se implementan los métodos, la
clase pasa a ser “abstracta” (no se puede instanciar).
• Ejemplo 1:
class UnaClase implements UnInterface
{
void mensaje1() { System.out.println(“1”); }
void mensaje2() { System.out.println(“2”); }
}
• Ejemplo 2:
class Automobile implements Driveable
{
public boolean startEngine()
{
if (notTooCold) engineRunning = true; ...
}
public void stopEngine()
{ ...
engineRunning = false;
}
public float accelerate(float acc)
{ ...
}
public boolean turn(Direction dir)
{ ...
}
}
Programación III Tema 3 - Interfaces
29. Implementación de interfaces (2)
• En estos momentos:
– La clase Automobile implementa el interface Driveable
– La clase Automobile posee un tipo “extra”: El tipo Driveable
– Todos los objetos de la clase Automobile pertenecen también al tipo Driveable
• Un interface puede ser implementado por más de una clase
class Automobile implements Driveable
{ ...
}
class LawnMower implements Driveable
{ ...
}
– En cualquier lugar donde se requiera un objeto del tipo Driveable podremos situar un
objeto de la clase Automobile o de la clase LawnMower. De esta forma nos
aseguramos que los métodos existen aunque no nos preocupa su implementación real.
Estamos definiendo una API, una interfaz de programación que asegura un concepto,
no una implementación concreta.
Automobile auto = new Automobile();
Lawnmower mower = new Lawnmower();
Driveable vehicle;
vehicle = auto;
vehicle.startEngine();
vehicle.stopEngine();
...
vehicle = mower;
vehicle.startEngine();
vehicle.stopEngine();
Programación III Tema 3 - Interfaces
30. Interfaces - ejemplo
• interfaz Comparable
– Método int compareTo(Object o)
• Devuelve -1, 0, +1
• Todas las clases que sean ordenables pueden
implementar este interfaz
• ¿Qué ventajas tiene el programador?
– Regularidad: siempre se compara igual
– Polimorfismo:
• void ordenaGrupo( Comparable c[] )
Programación III Tema 3 - Interfaces
31. Implem. de interfaces múltiples (1)
• Una clase puede implementar más de un interface
(herencia múltiple)
– Ejemplo 1:
interface A
{
void mensaje1();
void mensaje2();
}
interface B
{
void mensaje3();
void mensaje4();
}
class C implements A, B
{
void mensaje1() {System.out.println(“1”);}
void mensaje2() {System.out.println(“2”);}
void mensaje3() {System.out.println(“3”);}
void mensaje4() {System.out.println(“4”);}
}
Programación III Tema 3 - Interfaces
32. Implem. de interfaces múltiples (2)
– Ejemplo 2:
• Tenemos un nuevo interface: el interface Cloneable
interface Cloneable
{
Object clone();
}
• Tenemos una clase base para todos los tipos de vehículos llamada Vehicle
• Definamos Automobile:
class Automobile extends Vehicle implements Driveable, Cloneable
{ ...
public boolean startEngine() { ... }
public void stopEngine() { ... }
public float accelerate( float acc ) { ... }
public boolean turn( Direction dir ) { ... }
public Object clone() { ... }
}
• Automobile debe implementar los métodos de todos los interfaces que
implemente si se quiere poder instanciar objetos de tipo Automobile.
• Los objetos de la clase Automobile pertenecerán a 4 tipos distintos
(se podrán usar como si fueran de cualquiera de esos tipos):
– El tipo Automobile
– El tipo Vehicle
– El tipo Driveable
– El tipo Cloneable
Programación III Tema 3 - Interfaces
33. Herencia de interfaces
• Los interfaces pueden heredar mediante extends
interface A
{
void mensaje1();
}
interface B extends A
{
void mensaje2();
}
• Una clase que implemente el interface B deberá implementar los métodos de ambos
interfaces si quiere poder crear objetos.
class C implements B
{
void mensaje1() {System.out.println(“1”);}
void mensaje2() {System.out.println(“2”);}
}
• Además, Java admite la herencia múltiple entre interfaces
interface A {
void mensaje1();
}
interface B extends A {
void mensaje2();
}
interface C extends A {
void mensaje3();
}
interface D extends B, C {
void mensaje4();
}
• La clase que implemente el interface D deberá implementar los 4 métodos si quiere que se
puedan instanciar objetos.
Programación III Tema 3 - Interfaces
34. Ejemplo: Interfaces y clases abstractas
interface ElementoVolador
{
void acelerar( int vel );
}
interface ElementoMecanicoVolador extends ElementoVolador
{
void arreglarMecanismos();
}
abstract class Avion implements ElementoMecanicoVolador
{
boolean elMotorFunciona;
public void arreglarMecanismos()
{
elMotorFunciona = true;
}
}
class AvionComercial extends Avion
{
int velocidad;
public void acelerar( int vel )
{
velocidad += vel;
}
}
Programación III Tema 3 - Interfaces
35. Ejercicios propuestos (1)
• Implementación de Enumeration
• Queremos incorporar en la clase ListaEnlazada el interface de
java.util.Enumeration. Para ello:
– Definiremos una clase de paquete EnumeradorLista que implemente el
interface de Enumeration sobre una lista enlazada. Esto es, tiene que tener
un constructor que inicialice la secuencia, un método de comprobación de
final hasMoreElements() y un método de extracción del siguiente elemento
de la secuencia nextElement().
– Para evitar que esta clase la tenga que manipular directamente el usuario
incorporaremos a la clase ListaEnlazada un método enumeracion() que
devuelva una instancia de EnumeradorLista inicializada sobre la propia lista.
– Así, desde un programa podremos para recorrer cualquier lista y hacer algo
así como:
java.util.Enumeration e = l.enumeracion();
while (e.hasMoreElements())
{
System.out.print( " " + e.nextElement() );
}
– Esta clase EnumeradorLista es el clásico ejemplo de uso de clase interna.
Probar a definirla así.
– Cambiar la clase ListaEnlazada de acuerdo a todo esto. Probar en el main
que efectivamente la enumeración funciona.
Programación III Tema 3 - Interfaces
36. Ejercicios propuestos (2)
• Jerarquía de figuras
– Crear una clase llamada Figura de la que extiendan las clases Cuadrado,
Triángulo y Círculo. Figura debe ser una clase abstracta que contenga dos
métodos void dibujar() y void borrar(). Por otro lado, cada clase
descendiente de Figura va a redefinir estos métodos visualizando por
pantalla, en cada caso, un mensaje.
• (Por ejemplo: “Dibujando cuadrado/triángulo/círculo”, “Borrando
cuadrado/triángulo/círculo”).
– Crear por otro lado una clase Pizarra que tenga un atributo que sea un array
de Figuras. Además, tendrá un método para añadir Figuras al array y otro
para borrar todas las figuras del array.
• Para probar el funcionamiento, realizar una clase Ejemplo que añada varias
figuras (de cualquier tipo) a la pizarra. Ir viendo lo que saldría por pantalla para
ver cómo funciona el polimorfismo. También se puede llamar al método borrar
de la clase Pizarra para ver cómo se irían borrando todas las figuras.
– Jerarquía de figuras + Interfaces
• Modificar el ejercicio anterior de la siguiente forma:
– Definir un interface llamado Coloreable que hace referencia a todos los objetos que
admiten un color, definiendo los métodos void cambiaColor( Color c ) que cambia el
color del objeto y el Color queColor() que devuelve el color del objeto.
– Hacer que Figura implemente el interfaz Coloreable, añadiendo los métodos y
atributos necesarios. ¿Dónde implementarías estos métodos? Hazlo.
Programación III Tema 3 - Interfaces