Herencia y Poliformismo Java

49
1 4.- Herencia y polimorfismo 1. Herencia 2. Polimorfismo 3. Interfaces

Transcript of Herencia y Poliformismo Java

Page 1: Herencia y Poliformismo Java

1

4.- Herencia y polimorfismo

1.  Herencia 2.  Polimorfismo 3.  Interfaces

Page 2: Herencia y Poliformismo Java

2

1. Herencia

1.1. Introducción 1.2. Los constructores en la herencia 1.3. Modificadores de acceso 1.4. La clase Object 1.5 Herencia vs. composición

Page 3: Herencia y Poliformismo Java

3

1.1.- Introducción •  La herencia permite definir clases (subclases) a partir de otra clase

más genérica (superclase). •  La subclase reúne todas la propiedades de la superclase, además

de las suyas propias. •  La herencia potencia la reutilización de código, genera código

más fiable y robusto y reduce el coste de mantenimiento.

Persona

Estudiante

Persona nombre apellidos dni

mostrarNombre mostrarDNI

Estudiante numExpediente

mostrarNumExp

class Estudiante extends Persona { . . .

Page 4: Herencia y Poliformismo Java

4

class Persona(){ String nombre, apellidos, dni; void mostrarNombre(){ System.out.println(“Nombre: ” + apellidos + “,” + nombre); } void mostrarDNI() { System.out.println(“DNI: ” + dni); } }

class Estudiante extends Persona { String numExpediente; void mostrarNumExp(){ System.out.println(“Núm. Exp. ” + numExpediente); } }

class Ejemplo { public static void main(String args[]) { Estudiante e = new Estudiante(); e.nombre = “Ana”; e.apellidos = “García”; e.dni = “1234567”; e.numExpediente = “10001”; e.mostrarNombre(); e.mostrarNumExp(); } }

Page 5: Herencia y Poliformismo Java

5

1.1.- Introducción •  En Java no se permite la herencia múltiple.

A B

C

A

B C

Error Correcto

•  Una subclase hereda todos los métodos y atributos de la superclase EXCEPTO: –  Atributos y métodos privados –  Constructores (no se heredan pero sí se ejecutan)

Page 6: Herencia y Poliformismo Java

6

1.2.- Los constructores en la herencia •  Conceptos previos: toda clase, por defecto, contiene un constructor sin

parámetros y vacío.

class Esfera(){ double radio; Esfera() {} // Este constructor existe sin necesidad de escribirlo }

Esfera e1 = new Esfera(); Incorrecto. No existe constructor sin parámetros Esfera e2 = new Esfera(10); Correcto

•  El constructor por defecto se pierde si escribimos cualquier otro constructor.

class Esfera(){ double radio; Esfera(double r) { radio = r; } }

Esfera e = new Esfera(); Correcto

Page 7: Herencia y Poliformismo Java

7

1.2.- Los constructores en la herencia •  Los constructores no se heredan.

class Esfera(){ double radio; Esfera(double r) { radio = r; } Esfera() { radio = 1; } } class Planeta extends Esfera { int numSatelites; Planeta(double r, int ns) { radio = r; numSatelites = ns; } }

Planeta p1 = new Planeta(6378, 1); ¿Correcto / Incorrecto? Planeta p2 = new Planeta(6378); ¿Correcto / Incorrecto? Planeta p3 = new Planeta(); ¿Correcto / Incorrecto? Esfera e = new Esfera(6378); ¿Correcto / Incorrecto?

Page 8: Herencia y Poliformismo Java

8

•  Cuando creamos un objeto de una subclase, el constructor de la clase padre TAMBIÉN se ejecuta:

class A(){ A() { System.out.println(“En A”); } } class B extends A { B() { System.out.println(“En B”); } } class Demo { public static void main(String args[]) { B b = new B(); } }

Salida por pantalla: En A En B

1.2.- Los constructores en la herencia

•  Primero se ejecuta el constructor de la superclase y luego el de la subclase

Page 9: Herencia y Poliformismo Java

9

•  ¿Qué constructor se ejecuta en la superclase? → El constructor sin parámetros, a no ser que “digamos lo contrario”

class A(){ int i; A() { i = 0; } A( int i ){ this.i = i; } } class B extends A { int j; B() { j = 0; } B( int j ){ this.j = j; } } class Demo { public static void main(String args[]) { B b1 = new B(); System.out.println(“i=“ + b1.i + “j=“ + b1.j); B b2 = new B(5);System.out.println(“i=“ + b2.i + “j=“ + b2.j); } }

Salida por pantalla: i=0 j =0 i=0 j=5

1.2.- Los constructores en la herencia

Page 10: Herencia y Poliformismo Java

10

•  ¿Cómo podemos forzar la ejecución de un constructor determinado en la clase padre (superclase)?

class B extends A { int j; B() { j = 0; } B( int j ){ super(j); // Ejecuta un constructor en la superclase que // contiene un entero como argumento this.j = j; } }

Salida por pantalla: i=0 j =0 i=5 j=5

1.2.- Los constructores en la herencia

•  Si utilizamos super, ésta debe de ser la primera instrucción del constructor. De este modo se respeta el orden de ejecución de los constructores.

Page 11: Herencia y Poliformismo Java

11

•  Pérdida del constructor por defecto: class Esfera { Esfera ( double r ) { radio = r; } } class Planeta extends Esfera { int numSatelites; Planeta( double r, int ns ) { radio = r; numSatelites = ns; } }

1.2.- Los constructores en la herencia

•  Cuando creo un objeto de tipo Planeta, ¿qué constructor se ejecuta en la clase Esfera?

Page 12: Herencia y Poliformismo Java

12

class Esfera { Esfera() { radio = 1; } Esfera ( double r ) { radio = r; } } class Planeta extends Esfera { int numSatelites; Planeta( double r, int ns ) { radio = r; numSatelites = ns; } }

1.2.- Los constructores en la herencia

class Esfera { Esfera ( double r ) { radio = r; } } class Planeta extends Esfera { int numSatelites; Planeta( double r, int ns ) { super(r); numSatelites = ns; } }

Solución a

Solución b (preferible)

Page 13: Herencia y Poliformismo Java

13

class A { A () { ... } A( int x ) { ... } } class B extends A { B() { ... } } class C extends A { C( int x ) { ... } } class D extends A { D( int x ) { super(x); } } class E extends D { E( int x ) { ... } }

1.2.- Los constructores en la herencia

B ob1 = new B(); C ob2 = new C(1); D ob3 = new D(1); E ob4 = new E(1); E ob5 = new E();

•  ¿Qué constructor se ejecuta en cada caso?

Page 14: Herencia y Poliformismo Java

14

1.3.- Modificadores de acceso

private Sin modificador

(friendly)

protected public

Misma clase Si Si Si Si

Otra clase del mismo paquete

No Si Si Si

Subclase de diferente paquete

No No Si Si

No subclase de diferente paquete

No No No Si

Page 15: Herencia y Poliformismo Java

15

1.4.- La clase Object •  Object es la clase base (superclase) de todas las demás clases. •  Si una clase no especifica extends, entonces se entiende que

deriva de Object → Todas las clases derivan directa o indirectamente de Object.

•  Algunos métodos de la clase Object: –  boolean equals (Object o): compara dos objetos. –  String toString(): devuelve una cadena de tipo String que contiene una

descripción del objeto. Se invoca automáticamente cuando se utiliza el objeto como si fuera una cadena:

–  void finalize(): se ejecuta automáticamente al destruirse el objeto.

Complejo c = new Complejo(); System.out.println(“c = ” + c);

Page 16: Herencia y Poliformismo Java

16

1.5.- Herencia vs. composición •  No debe confundirse la herencia con la composición. •  Composición: mecanismo por el que se define una nueva clase

agregando componentes de otras clases.

class Punto { int x, y; . . . } class Figura { Punto origen; . . .

class Punto { int x, y; . . . } class Figura extends Punto{ . . .

•  Dadas dos clases A y B: –  ¿A es un B? → Herencia –  ¿A tiene un B? → Composición

class A extends B {

class A { B b;

•  Una figura no es un punto. Una Figura tiene un punto de origen. •  Un círculo es una figura. Un círculo no tiene una figura.

Page 17: Herencia y Poliformismo Java

17

2. Polimorfismo

2.1. Introducción 2.2. Sobreescritura de métodos 2.3. La conversión hacia arriba 2.4. Enlace dinámico y polimorfismo 2.5. Clases abstractas 2.6. La conversión hacia abajo 2.7. Sobreescribir métodos de Object

Page 18: Herencia y Poliformismo Java

18

2.1- Introducción •  El polimorfismo es la capacidad que tienen los LOO de ofrecer distintas

implementaciones para un mismo método:

Polimorfismo ≡ múltiples formas

•  Una llamada a un mismo método puede tener comportamientos distintos. •  Enlace estático o temprano (polimorfismo en tiempo de compilación)

–  Sobrecarga de métodos

Complejo c1, c2, c3; . . . c3 = c1.multiplica(c2); // Método polimórfico (sobrecargado) c3 = c1.multiplica(4); // Método polimórfico (sobrecargado)

–  En tiempo de compilación se establece el enlace con el código que deberá ejecutarse.

•  Enlace dinámico o tardío (polimorfismo en tiempo de ejecución) –  Sobreescritura de métodos. –  No es posible determinar en tiempo de compilación el método que se ejecutará. –  Permite realizar ciertas abstracciones sobre los tipos de datos con los que se

trabaja.

Page 19: Herencia y Poliformismo Java

19

2.2- Sobreescritura de métodos •  En ocasiones interesa que la subclase modifique algunos de los

métodos heredados para que tengan un comportamiento distinto:

class Nave { int posX, posY, municion; . . . void disparar() { if(municion>0) municion--; } } class NaveConEscudo extends Nave { boolean escudo; . . . void activarEscudo() { escudo = true; } void desactivarEscudo() { escudo = false; } // Sobreescritura del método disparar void disparar() { if( municion>0 && escudo==false ) municion--; } }

Page 20: Herencia y Poliformismo Java

20

2.2- Sobreescritura de métodos

class Juego { public static void main( String [] args ) { Nave nave1 = new Nave(); NaveConEscudo nave2 = new NaveConEscudo();

. . . nave1.disparar(); // disparar de Nave nave2.disparar(); // disparar de NaveConEscudo } }

Page 21: Herencia y Poliformismo Java

21

2.2- Sobreescritura de métodos •  Hay dos formas de sobreescribir un método:

–  Reemplazo: se reescribe el método completamente, ignorando el código de la superclase.

–  Refinamiento: se amplía el método de la superclase con instrucciones extras.

class Persona { String nombre, dni; . . . void mostrarDatos() { System.out.println(“Nombre:” + nombre); System.out.println(“DNI: ” + dni); } } class MiembroUPV extends Persona { String email; . . . void mostrarDatos() { // Refinamiento super.mostrarDatos(); // Mostrar datos de Persona System.out.println(“EMAIL: ” + email); } }

Page 22: Herencia y Poliformismo Java

22

2.2- Sobreescritura de métodos •  Si se declara un método como final, se impide su sobreescritura.

class Persona { String nombre, dni; . . . final void derechosFundamentales() { System.out.print(nombre + “ tiene derecho a ”); System.out.print(“una alimentación adecuada.”); } }

•  Si se declara una clase como final, se impide que se extienda.

final class Math { . . .

Page 23: Herencia y Poliformismo Java

23

2.3- La conversión hacia arriba

•  Sin embargo es posible declarar una referencia de tipo A y emplearla para instanciar un objeto de tipo B, siempre y cuando B sea una subclase (o un subtipo) de A.

A ref = new B();

•  Hasta ahora el tipo de la referencia y el tipo del objeto instanciado han coincidido: A ref = new A();

Se denomina: •  Tipo estático: el tipo con el que se declara la referencia. •  Tipo dinámico: el tipo del objeto instanciado.

En la sentencia: A ref = new B(); –  Tipo estático de ref: A –  Tipo dinámico de ref: B

Page 24: Herencia y Poliformismo Java

24

2.3- La conversión hacia arriba •  Hablamos de conversión hacia arriba cuando se instancia un

objeto mediante una referencia perteneciente a un tipo o clase que jerárquicamente está “arriba”de la clase del objeto instanciado.

Esfera

Planeta

Esfera e; e = new Planeta(); // Conversión hacia arriba

Tipo estático de e: Esfera Tipo dinámico de e: Planeta

•  Limitaciones: sólo se tiene acceso a los miembros definidos en el tipo estático.

•  En el ejemplo anterior, aunque se ha creado un objeto de tipo Planeta, mediante e sólo se tiene acceso a los atributos y métodos de Esfera.

Page 25: Herencia y Poliformismo Java

25

2.3- La conversión hacia arriba class A { public void m1() { . . . } } class B extends A { public void m2() { . . . } }

B obj1 = new B(); // Tipo estático y dinámico de obj1: B A obj2 = new B(); // Tipo estático A y tipo dinámico B B obj3 = new A(); // Tipo estático B y tipo dinámico A. ¡ERROR!

m2()

B A m1()

m2()

B A m1()

A m1()

obj1 obj2 obj3

B obj1 = new B() A obj2 = new B() B obj3 = new A()

obj1.m1() OK obj1.m2() OK

obj2.m1() OK obj2.m2() ERROR

ERROR

Page 26: Herencia y Poliformismo Java

26

2.3- La conversión hacia arriba •  Conversión hacia arriba + sobreescritura

¿Para qué sirve todo esto?

class A { public void m1() { . . . } } class B extends A { // Sobreescribimos m1 public void m1() { . . . } public void m2() { . . . } }

A obj = new B(); obj.m1(); // ¿Qué método m1 se ejecuta? ¿El de A o el de B?

•  El tipo estático determina QUÉ se puede hacer. El tipo dinámico determina CÓMO se hace.

Page 27: Herencia y Poliformismo Java

27

2.4- Enlace dinámico y polimorfismo class Figura { Color c; double area() { return 0; // No sabemos qué área tiene una // figura genérica } } class Rectangulo extends Figura { double alto, ancho; . . . double area() { // Sobresscritura del metodo area return alto*ancho; } } class Circulo extends Figura { double radio; . . . double area() { // Sobresscritura del metodo area return Math.PI*radio*radio; } }

Page 28: Herencia y Poliformismo Java

28

2.4- Enlace dinámico y polimorfismo public class EnlaceDinamico { public static void main(String[] args) { // Creamos 10 referencias de tipo Figura Figura [] v = new Figura[10]; // En función de ciertas acciones tomadas por el // usuario creamos rectángulos o círculos for(int i=0; i<10; i++) { if( el_usuario_realiza_cierta_accion ) v[i] = new Rectangulo(10,10); // Conv. hacia arriba else v[i] = new Circulo(5); // Conv. hacia arriba } // Mostramos las áreas de las figuras creadas for(int i=0; i<10; i++) { double a = v[i].area(); // Enlace dinámico System.out.println("Area="+a); } } }

Page 29: Herencia y Poliformismo Java

29

2.4- Enlace dinámico y polimorfismo •  El polimorfismo permite realizar ciertas abstracciones sobre los

tipos de datos. •  No es necesario conocer el tipo exacto de los datos para poder

realizar ciertas operaciones. ¡Puedo obtener el área de una figura, o dibujarla, sin saber exactamente de qué figura se trata!

•  La siguiente clase permite dibujar un conjunto de figuras, ¡sin necesidad de conocer de qué tipo de figuras se trata!

class ConjuntoDeFiguras { Figura [] v = new Figura[1000]; int numFiguras = 0; void añadirFigura( Figura f ) { // El objeto pasado como parámetro v[numFiguras++] = f; // puede ser una subclase de Figura } // (conversión hacia arriba) void dibujaTodo() { for(int i=0; i<numFiguras; i++) { v[i].dibuja(); // Desconozco qué tipo de figura } // estaré dibujando } }

Page 30: Herencia y Poliformismo Java

30

2.4- Enlace dinámico y polimorfismo

class Ordena { static void seleccionDirecta( Conjunto c ) { int pos_min, N = c.getNumElementos(); for( int i = 0; i <= N-2; i++ ) { pos_min = i; for( int j = i+1; j < N; j++ ) { if( c.menor(j, pos_min) ) pos_min = j; } c.intercambiar(i, pos_min); } } }

•  La siguiente clase permite ordenar conjuntos de cualquier tipo (números enteros, colores, personas, …)

•  Requerimientos: –  El objeto que le pasemos como parámetro al método

seleccionDirecta debe ser un subtipo (subclase) de Conjunto. –  La clase Conjunto debe contener los métodos getNumElementos,

menor e intercambiar. –  El objeto que pasemos como parámetro puede tener sobreescritos los

métodos de la clase Conjunto.

Page 31: Herencia y Poliformismo Java

31

2.4- Enlace dinámico y polimorfismo

class Figura { . . . double area() { return 0; }

boolean mismaArea(Figura otra) { return this.area() == otra.area(); } } class Rectangulo extends Figura { . . . double area() { return alto * ancho; } } class Circulo extends Figura { . . . double area() { return Mat.PI * radio * radio; } }

•  Una situación algo más compleja:

•  ¿Qué método ejecuta en la llamada this.area()?

Page 32: Herencia y Poliformismo Java

32

2.5- Clases abstractas

class Figura { . . . } class Rectangulo extends Figura { . . . double area() { return alto * ancho; } } class Circulo extends Figura { . . . double area() { return Mat.PI * radio * radio; } }

•  Si no vamos a utilizar nunca el método area de la clase Figura, podríamos quitarlo…

Figura [] v = new Figura[10]; . . . // Añado a v Rectangulos y Circulos for(int i=0; i<v.length; i++) System.out.println(“Area=“ + v[i].area());

…pero, ¿es correcto el siguiente código?

Page 33: Herencia y Poliformismo Java

33

2.5- Clases abstractas •  Tiene poco sentido implementar un método que nunca

voy a utilizar.

•  Además, si en Figura implementamos el método area, existe la posibilidad de que alguna subclase no implemente su propia versión de area, en cuyo caso heredaría la implementación (errónea) dada en Figura.

•  Lo ideal sería:

1.  Incluir el método area pero no implementarlo (sin código)

2.  Obligar a las subclases directas que lo implementen

Page 34: Herencia y Poliformismo Java

34

2.5- Clases abstractas abstract class Figura { . . . abstract double area(); } class Rectangulo extends Figura { . . . double area() { return alto * ancho; } } class Circulo extends Figura { . . . double area() { return Mat.PI * radio * radio; } }

•  El método area es abstracto. Se incluye la cabecera del método (tipo, nombre y parámetros) pero no la implementación (el código).

•  Como la clase Figura tiene un método abstracto, también debe ser abstracta.

•  Las subclases de Figura deberán implementar el método area.

Page 35: Herencia y Poliformismo Java

35

2.5- Clases abstractas Cosas que hay que saber:

•  Una clase abstracta no puede ser instanciada.

•  Si una subclase que extiende una clase abstracta no implementa alguno de los métodos abstractos declarados en la superclase, entonces debe ser declarada también como abstracta.

•  Una clase abstracta puede tener métodos no abstractos.

•  Se pueden declarar variables referencia cuyo tipo sea una clase abstracta.

•  Aunque las clases abstractas no se pueden instanciar, sí que pueden tener constructores.

Page 36: Herencia y Poliformismo Java

36

2.5- Clases abstractas abstract class Figura { int origenX, origenY; Color color; Figura(int x, int y, Color c) { origenX = x; origenY = y; color = c; } void mover(int despX, int despY) { origenX += despX; origenY += despY; } abstract double area(); } class Circulo extends Figura { private double radio; Circulo(int x, iny y, double r, Color c) { super(x, y, c); radio = r; } double area() { return Mat.PI * radio * radio; } void setRadio(int r) { radio = (r>=0 ? r : 0); } }

Page 37: Herencia y Poliformismo Java

37

2.6- La conversión hacia abajo •  Conversión hacia arriba: se gana generalidad pero se pierde

información acerca del tipo concreto con el que se trabaja. Figura f; f = new Circulo(...);

•  Qué ocurre si quiero hacer una operación propia del tipo concreto con el que estoy trabajando? f.setRadio(5); // Error

•  Conversión hacia abajo: cambio del tipo de la referencia a un subtipo (a un tipo que jerárquicamente está “por abajo”).

Figura f = new Circulo(...); // Conversión hacia arriba . . . Circulo c; c = (Circulo)f; // Conversión hacia abajo c.setRadio(5); // Correcto

•  O simplemente:

((Circulo)f).setRadio(5);

Page 38: Herencia y Poliformismo Java

38

2.6- La conversión hacia abajo •  Peligros de la conversión hacia abajo: Debo estar seguro de

convertir la referencia al tipo correcto.

•  ¿Cómo puedo conocer el tipo dinámico de f? Solución: instanceof

Figura f; if(cierta_condicion) f = new Circulo(...); else f = new Rectangulo(...);

if ( f instanceof Circulo ) // f es un círculo ((Circulo)f).setRadio(5); else if ( f instanceof Rectangulo ) // f es un rectángulo ((Rectangulo)f).setDim(5,5);

Page 39: Herencia y Poliformismo Java

39

2.6- La conversión hacia abajo •  La conversión hacia abajo debemos usarla cuando no haya otra

solución posible. •  Se pierde la abstracción y generalidad que habíamos ganado con la

conversión hacia arriba. •  Si lo que pretendía era cambiar el tamaño de la figura, hubiese sido

preferible la siguiente solución:

abstract class Figura { . . . abstrac void zoom( double factorEscala); } class Circulo extends Figura { . . . void zoom( double factorEscala ) { radio *= factorEscala; } } class Rectangulo . . . void zoom( double factorEscala ) { base *= factorEscala; altura *= factorEscala; } }

Page 40: Herencia y Poliformismo Java

40

2.7- Sobreescribir métodos de Object •  La clase Object tiene métodos que puede interesar sobreescribir.

–  boolean equals (Object o): compara dos objetos. –  String toString(): devuelve una cadena de tipo String que contiene una

descripción del objeto. Se invoca automáticamente cuando se utiliza el objeto como si fuera una cadena:

–  void finalize(): se ejecuta automáticamente al destruirse el objeto. •  Uso del método toString:

Complejo c = new Complejo(2,3); System.out.println(c);

•  Al utilizar c como si fuera un String, se invoca automáticamente al método toString. System.out.println(c.toString());

•  Si no está sobreescrito, se invova toString de Object. •  No esperemos que Object sepa cómo mostrar un Complejo.

Page 41: Herencia y Poliformismo Java

41

2.7- Sobreescribir métodos de Object •  Sobreescritura de toString: class Complejo { double real, imag; . . . public String toString() { String s = real + “+” + imag + “i”; return s; } }

Complejo c = new Complejo(2,3); System.out.println(c); // Se invoca el método toString

•  Salida por pantalla: 2+3i

Page 42: Herencia y Poliformismo Java

42

3. Interfaces

3.1. Introducción 3.2. Declaración e implementación de interfaces 3.3. Polimorfismo mediante interfaces 3.4. Definición de constantes 3.5. Herencia entre interfaces

Page 43: Herencia y Poliformismo Java

43

3.1- Introducción •  En Java no existe la herencia múltiple.

•  Las interfaces ofrecen algunas de las ventajas de la herencia múltiple sin ninguno de sus inconvenientes.

•  Una interfaz guarda muchas similitudes con una clase abstracta con todos sus métodos abstractos y atributos constantes y estáticos (final static).

A B

C

No genera conflictos si todos los métodos de A y B son abstractos.

Page 44: Herencia y Poliformismo Java

44

3.2.- Declaración e implementación de interfaces

•  Declaración: acceso interface nombre_interfaz { [public static final] tipo var1; [public static final] tipo var2; ... [public] tipo metodo1( ... ) ; [public] tipo metodo2( ... ) ; }

interface Coleccion { void añadirElemento( Object o ); int getNumElementos(); void mostrar(); }

•  Ejemplo:

Page 45: Herencia y Poliformismo Java

45

3.2.- Declaración e implementación de interfaces

•  Una interfaz define qué operaciones se pueden realizar pero no especifica cómo se realizan.

•  Una interfaz puede ser implementada por una o varias clases.

•  Todo lo que tiene que hacer una clase para implementar una interfaz es sobreescribir todos sus métodos.

class Conjunto implements Coleccion { private Object[] v; private int numElementos;

public void añadirElemento( Object o ) { . . . } public int getNumElementos() { . . . } public void mostrar() { . . . } }

Page 46: Herencia y Poliformismo Java

46

3.2.- Declaración e implementación de interfaces

•  Es posible que varias clases sin relación de herencia implementen una misma interfaz y que una misma clase implemente varias interfaces.

I2

E F

B

C D

A

I1

Page 47: Herencia y Poliformismo Java

47

3.3.- Polimorfismo mediante interfaces

•  Una interfaz es un tipo de dato. Es posible declarar referencias de tipo interfaz (aunque no se puedan instanciar objetos de este tipo).

•  La conversión hacia arriba se puede aplicar también a las interfaces. interface Coleccion { void añadir(Elemento e); void borrar(Elemento e); } class Conjunto implements Colección { . . . } class ListaEnlazada implements Colección { . . . } class Ejemplo { public static void main(String [] args) { Coleccion c; c = new Conjunto(); // Conv. Hacia arriba c.añadir( ... ); . . .

Page 48: Herencia y Poliformismo Java

48

3.4.- Definición de constantes

•  Las interfaces también pueden emplearse para definir constantes

•  Aunque no se especifique explícitamente, los atributos de una interfaz siempre son estáticos y constantes (static final).

interface CteMat{ double pi = 3.14159265; double e = 2.71828182; } class Ejemplo { public static void main(String [] args) { double r = 4; double area = CteMat.pi * r * r; . . .

Page 49: Herencia y Poliformismo Java

49

3.5.- Herencia entre interfaces

•  Es posible definir herencia entre interfaces.

•  Se permite la herencia múltiple.

interface I1 { void metodo1(); void metodo2(); } interface I2 { void metodo3(); } interface I3 extends I1, I2 { void metodo4(); } class C implements I3 { // Deberá implementar metodo1, metodo2, // metodo3 y metodo4 }