Fundamentos de Programación Tema 7: Relaciones entre clases Dpto. de Ingeniería de Sistemas Telemáticos http://www.lab.dit.upm.es/~fprg/ nov-07 1 Índice Introducción Encapsulado Composición Interface Extensión Herencia Polimorfismo Herencia e interfaces Criterios nov-07 2 Historia Tradicionalmente el código se reutilizaba por el sistema de cortar aquí y pegar allá manual difícil mantenimiento posterior nunca se cierra nada Los objetos abren nuevas posibilidades encapsulación de datos y métodos de uso composición extensión: herencia y polimorfismo nov-07 3 1 Interfaces Se intenta distinguir entre lo que hay que hacer: interface cómo se hace: class La interfaz sirve de especificación e incluso de contrato entre las partes La clase es el producto que satisface aquella especificación Java proporciona soporte sintáctico y semántico para estos conceptos nov-07 4 Índice Introducción Encapsulado Composición Interface Extensión Herencia Polimorfismo Herencia e interfaces Criterios nov-07 5 Encapsulación Una clase contiene los datos que recogen lo que es y/o cómo está los métodos que permiten acceder a ese estado, bien sea para crearlo (constructores), leerlo o actualizarlo Si las variables que mantienen el estado son privadas, sólo los métodos pueden modificarlas y por tanto el autor de los métodos puede y debe responsabilizarse de su corrección nov-07 6 2 ADT: tipos abstractos de datos Si las variables que representan el estado de un objeto son privadas, se puede modificar la forma de representarlo sin que los usuarios de la clase se enteren los métodos proporcionan toda la interfaz se dice que la clase es un tipo abstracto de datos (ADT) porque no se sabe la forma concreta de representar los datos nov-07 7 Índice Introducción Encapsulado Composición Interface Extensión Herencia Polimorfismo Herencia e interfaces Criterios nov-07 8 Composición Un objeto incorpora otro(s) objeto(s) como parte integral class B { A varA; ... } se dice que los objetos B tienen un objeto A Típicamente los objetos internos son PRIVATE los objetos internos se inicializan vía constructor nov-07 9 3 Relación de composición Punto Cuadrado 4 1 Cubo 6 1 Asociaciones: • 0..1 cero a uno •1 uno • 0 .. * cero a muchos • 1 .. * uno a muchos nov-07 10 ¿Cuándo usar composición? Cuando se necesita la funcionalidad de otra clase dentro de este; pero no su interfaz por eso son PRIVATE Cuando hay más de 1 objeto que incorporar nov-07 11 Índice Introducción Encapsulado Composición Interface Extensión Herencia Polimorfismo Herencia e interfaces Criterios nov-07 12 4 Interface Indica de qué métodos disponemos sin entrar en detalles Aporta constantes Java determina la sintaxis, que puede chequear el compilador insinúa la semántica, que se aporta por medio de comentarios nov-07 13 Ejemplos interface Coordenada { double x (); double y (); double distancia (Coordenada q); } interface Poligono { int numero_vertices (); Coordenada vertice (int i); double perimetro (); double superficie (); void escala (double proporcion); } nov-07 14 ¿Constructores? No, gracias porque no sabemos cómo se hace sólo sabemos que cuando exista, tendrá ciertos métodos ¿pudiera tener más? • si; pero ¿cómo se sabe que hay lo que no se ha pedido? Pero ... pueden haber métodos que enriquecen nov-07 15 5 Implementación Es aquella clase “normal” que hace todo lo que prometía la interface Habitualmente, incluye constructores class Cartesiana implements Coordenada { private double x, y; Cartesiana (double _x, double _y) { x= _x; y= _y; } double x () { return x; } double distancia (Coordenada q) { double dx= q.x()-x; double dy= q.y()-y; return Math.sqrt(dx*dx + dy*dy); } } nov-07 16 Variables Pueden ser de una clase interface pero hay que crearlas con constructores reales Coordenada A= new Cartesiana (0.0, 0.0); Coordenada B= new Cartesiana (1.0, 1,0); Coordenada C= A; double d= A.distancia(B); nov-07 17 Una clase multifunción Una misma clase puede implementar varias interfaces interface Mamifero { void amamanta (); } interface Oviparo { void ponHuevos (); } class Ornitorrinco implements Mamifero, Oviparo { ... } Ornitorrinco juliana= new Ornitorrinco(); juliana.ponHuevos(); juliana.amamanta(); nov-07 18 6 ¿Cuándo usar interfaces? Nunca es malo aunque a veces retarda la ejecución Cuándo sabe qué queremos; pero no sabemos (aún) cómo hacerlo lo hará otro lo haremos de varias maneras nov-07 19 Índice Introducción Encapsulado Composición Interface Extensión Herencia Polimorfismo Herencia e interfaces Criterios nov-07 20 Extensión class B extends A { ... } Se usa cuando A es interesante; pero necesitamos más funcionalidad Se dice que la clase B es una clase A ... enriquecida nov-07 21 7 Relación de extensión Animal Perro Gato nov-07 22 Herencia B hereda de A los componentes (atributos y métodos) y en particular, la interfaz (métodos públicos) B puede redefinir métodos de A se dice que los métodos de A quedan ocultos se puede acceder a los métodos ocultos super.metodoOculto () nov-07 23 Upcasting class B extends A { ... } Las variables de clase B sólo pueden referirse a objetos de clase B Las variables de clase A pueden referenciar objetos de clase A (normal) pueden referenciar objetos de clase B (upcasting) El upcasting es 100% seguro y siempre se puede aplicar varA= varB; nov-07 24 8 Downcasting class B extends A { ... } Downcasting varB= (B) varA; sólo vale si estamos invirtiendo un upcasting se lanzará una excepción (error) si el objeto referenciado no es realmente de clase B se puede chequear previamente if (varA instanceof B) varB= (B) varA; nov-07 25 Transitividad La relación de herencia es transitiva Se puede hacer upcasting una variable puede referenciar objetos de su propia clase, o de cualquier clase extendida a partir de ella Se puede hacer downcasting una variable se puede cargar con objetos referenciados por variables de clases antecesoras en la jerarquía de herencia pero la maniobra dará un error si no era un upcasting nov-07 26 Object Todas las clases de Java son extensiones de la clase Object (predefinida) Object x= new cualquierCosa (...); Por ejemplo, Object proporciona un método general public String toString (); que las clases pueden particularizar nov-07 27 9 ¿Cuándo usar extensión? Pese al tiempo que se le dedica en clase y a lo que ello hablan los libros, las extensiones se usan poco La única razón para extender una clase es poder aplicar upcasting Si hay dudas entre componer o extender, ¡componga! Razón: los programas son más fáciles de entender Si hay duda entre usar un atributo o extender, ¡use el atributo! nov-07 28 Modificación de métodos Un método se puede redefinir si Se mantiene la signatura (obvio) Se hace igual o más público privado -> (paquete) -> protegido -> público Lanza igual o menos excepciones Puede no lanzar nada Puede lanzar alguna clase derivada nov-07 29 final Se puede calificar como final Una variable cuyo valor no queremos que se pueda modificar Un argumento que no dejamos modificar Un método que no queramos que se pueda reemplazar (durante una extensión) Una clase que queramos que no se pueda extender Es interesante tener componentes finales Porque se entienden fácilmente, sin sorpresas El código se ejecuta más rápido nov-07 30 10 Constructores class B extends A { ... } Para inicializar un objeto hay que inicializar antes la parte heredada Los constructores de B empiezan llamando a los constructores de A Bien explícitamente El programador escribe el código de la llamada Bien implícitamente Si el programado no lo escribe: el compilador lo inyecta nov-07 31 ¿Dónde se inicializa? Lo lógico es inicializar los objetos en los constructores ... pero a veces el orden de llamada de constructores no es evidente y es más seguro y más legible usar un método “normal” que se llamará después de construir el objeto con todos los atributos a 0, null, etc. nov-07 32 Índice Introducción Encapsulado Composición Interface Extensión Herencia Polimorfismo Herencia e interfaces Criterios nov-07 33 11 Polimorfismo Si class B extends A Y B modifica un método M, y hacemos upcasting A varA= new B (); Si escribimos javac cree que nos referimos a varA.metodo( A.metodo() ) Pero java ejecuta B.metodo() nov-07 34 Clases abstractas Para aplazar detalles de implementación a clases derivadas basta decir la signatura del método sin detallar el cuerpo Se dice que el método es abstracto Una clase es abstracta si tiene uno o más métodos sin detallar No se pueden crear objetos de clases abstractas Hay que desarrollar el cuerpo antes de new En clases derivadas nov-07 35 Evolución de las piezas nov-07 clase abstracta extends clase extends extends extends new objeto 36 12 Índice Introducción Encapsulado Composición Interface Extensión Herencia Polimorfismo Herencia e interfaces Criterios nov-07 37 El objeto pasajero de avión nov-07 38 El objeto pasajero de avión El pasajero es todas estas cosa: SI!!!! El pasajero muestra siempre todas sus “personalidades” con cualquiera NO!!!! Podríamos intentar ligar con el jefe!!! Algo totalmente fuera de contexto En cada momento nos Comportamos de una forma determinada En cada momento ofrecemos un interfaz diferente, pero sin dejar de ser la misma persona, el mismo objeto nov-07 39 13 Comportamientos de los objetos Los objetos ofrecen diferentes comportamientos en diferentes contexto En el campo de la POO un comportamiento se refleja en un interfaz: Conjunto de elementos que se pueden usar/acceder desde el exterior Métodos públicos Atributos públicos nov-07 40 interface Cuando debe haber polimorfismo entre clases que no pertenecen a la misma jerarquía de herencia Tienen su propia sintaxis y su jerarquía de herencia Clase que sólo contiene cabeceras de métodos (no estáticos) campos estáticos y finales (constantes) No se pueden construir objetos de esa clase, aunque si tendremos variables que referencien objetos de esa clase. nov-07 41 Ejemplo interface Hablador { public void dice (); } class Radio implements Hablador { public void dice () { System.out.prinln(“Noticias”); } } abstract class Animal implements Hablador { protected String nombre; protected Animal (String nombre) { this.nombre= nombre; } nov-07 } 42 14 Ejemplo class Perro extends Animal { public void dice () { System.out.println(“Guau”); } } class Gato extends Animal { public void dice () { System.out.println(“Miau”); } } nov-07 43 Uso de interfaces Una clase puede implementar varios interfaces tiene que implementar todos los métodos abstractos si queda alguno sin implementación, la clase es abstracta Los interfaces son tipos podemos declarar referencias de ellos se les puede asignar objetos de clases que implementen los interfaces nov-07 44 Ejemplo class HabladorPrueba { public static void main (String args[]) { Hablador todos[]= new Hablador[3]; todos[0]= new Perro ("Rintintin"); todos[1]= new Gato ("Isidoro"); todos[2]= new Radio(); for (int i=0; i < todos.length; i++) todos[i].dice(); } } nov-07 45 15 Jerarquía de clases interface Heredan de (extienden a) otros interfaces Su jerarquía es diferente de la de las clases Permiten herencia múltiple (heredar de varios interfaces) nov-07 46 Ejemplo interface Mascota { public String propietario(); public void hazMoneria(); } nov-07 class perroDomestico extends Perro implements Mascota { protected String dueño; public perroDomestrico (String nombre, String dueño) { super (nombre); this.dueño= dueño; } public String propietario () { return dueño; } public void hazMoneria() { // código para hacer la gracia } 47 } Ejemplo interfaz Pintable { public void Pinta(); } interfaz FormaCerrada { public double Area(); public double Perimetro(); } class Circulo implements Pintable, FormaCerrada { ... } nov-07 48 16 Diagrama del diamante herencia múltiple: prohibida en java class A class B extends A class C extends A class D extends B, C nov-07 49 Diagrama del diamante implementación múltiple: permitida en java interface A interface B extends A interface C extends A class D implements B, C nov-07 50 Evolución de las piezas interface extends implements nov-07 clase abstracta extends clase extends extends extends new objeto 51 17 Extensión e implementación class B extends A 0 ó 1 clase “padre” implements I1, I2, ... { 0, 1, 2, ..., n interfaces ... } nov-07 52 Índice Introducción Encapsulado Composición Interface Extensión Herencia Polimorfismo Herencia e interfaces Criterios nov-07 53 ¿Cuándo usar ...? Use interfaces para recoger posibilidades “algo que pueda hacer xxx” Use clases abstractas: cuando haya que especificar el qué; pero no el cómo No se sepa, no convenga, ... Use el enlace tardío para aplazar detalles concretos Incluso hasta después de haber compilado nov-07 54 18 ¿Cuándo usar ...? Use polimorfismo para capturar diferentes formas de hacer una misma cosa La duda aparece cuando no está claro si basta un atributo o se necesita código diferente Síntoma: programación “switch” nov-07 55 Conclusiones La composición es la forma natural de agrupar objetos Los interfaces son esenciales para separar lo que se quiere de cómo se hace La herencia es muy elegante; pero hay que usarla sólo si aporta algo Con moderación Código más difícil de entender y modificar El polimorfismo permite aplazar los detalles hasta el tiempo de ejecución Una buena razón para usar la herencia nov-07 56 19