18/04/2004 3.6 Interfaces y Paquetes 3.6.1 Interfaces Interfaces, implementaciones, paquetes, organización de archivos Declaración, Herencia múltiple, supertipos y subtipos, implementación Introducción l l l Mecanismo de Interfaz es una manera de declarar tipos consistentes sólo de métodos abstractos y constantes Clases deben implementar los métodos de las interfaces Las interfaces son útiles para el diseño l l Clases deciden cómo implementar Una interfaz puede tener muchas implementaciones Interfaz vs. Clase Abstracta l l Interfaz es una simple lista de métodos abstractos (no implementados) Una interfaz se diferencia de una clase abstracta en: l l l l Ejemplo de Interfaz (1/2) l l Una interfaz no puede implementar ningún método, una clase abstracta si lo puede Una clase puede implementar varias interfaces, pero puede tener una única superclase Una interfaz no puede ser parte de una jerarquía de clases Clases no relacionadas pueden implementar una misma interfaz Ejemplo de Interfaz (2/2) Declaración de la interfaz Clase que puede monitorear variación de precios de las acciones ObservadorAcciones es una interfaz de un observador l Método cambioValor permite ser notificado de cambio precio l Un objeto de una clase que implementa esta interfaz se registra con método observarAcciones para ser notificado de cambios l accionMon permite definir la acción que interesa observar y delta la variación que ese considera interesante public interface ObservadorAcciones { final String enersisMon = ”Enersis"; final String santaIsabelMon= ”Santa Isabel"; final String copecMon = ”Copec"; void cambioValor(String accionMon , double nuevoValor); public class MonitorAcciones { public void observarAcciones (ObservadorAcciones observador, String accionMon, double delta) { ... } } } Constantes Método Cuerpo de la Interfaz 1 18/04/2004 Declaración de Interfaz public interfaz < nombre interfaz> extends <lista de super-interfaces> { <cuerpo de la interfaz> } Cuerpo de la interfaz l Todas las constantes son implícitamente: públicas, estáticas y finales l l l l Todos los métodos son implícitamente: públicos y abstractos l l l public hace pública la interfaz fuera del paquete (opcional) La interfaz puede extender varias interfaces (opcional) Implementación de una Interfaz l l l Una interfaz define un conjunto de métodos. Una referencia a una interfaz permite suponer que los métodos existen Una clase que “implementa” una interfaz se compromete a “implementarlos”. l l l Definir código para cada uno de ellos. Incumplimiento de contrato implica imposibilidad de crear instanciasàclase abstracta Se deja la responsabilidad a los hijos. Implementación de una Interfaz l l No se aceptan otros modificadores (e.g. private, protected y synchronized) Implementación de una Interfaz public interface ObservadorEventos { public void nuevoEvento(Date fecha, String evento); } public class Asistente implements ObservadorEventos { public void nuevoEvento(Date fecha, String evento){ System.out.println("Avisarle al jefe antes de las "+fecha+"!!"); } } public class Persona implements ObservadorEventos{ ... public void nuevoEvento(Date fecha, String evento){ System.out.println("Ir a tomar la micro para la '"+evento+"'!"); } } Implementación de una Interfaz public class Agenda { public static void main(String args[]){ private Vector observadores=new Vector(); Agenda a = n e w Agenda(); ... Persona p = new Persona("NN", "112233"); public void agregarObservador(ObservadorEventos o){ Asistente asist = new Asistente(); observadores.add(o); a.agregarObservador(p ); } a.agregarObservador(asist ); a.nuevoEvento ("reunion"); public void nuevoEvento(String evento){ for(int i=0;i<observadores.size();i++){ } ObservadorEventos oe = (ObservadorEventos) observadores.get(i); oe.nuevoEvento(new Date(), evento); } Ir a tomar la micro para la ‘reunion’! } } Avisarle al jefe antes de las Mon Apr 05 17:08:49 VET 2004!! 2 18/04/2004 Herencia Simple vs. Múltiple l l l l Una clase puede extender exactamente una superclase Una interfaz puede extender múltiples interfaces Herencia múltiple con clases puede producir problemas debido a diferentes implementaciones W Ejemplo: l l l Extensión de interfaces W tiene un campo wVar Si Z hace referencia a wVar, cuál es? Existen dos wVar? Y l l l Al igual que las clases, las interfaces pueden tener súper-interfaces. La interfaz hija “hereda” las definiciones de la interfaz padre. En este caso se permite herencia múltiple X Z Java evita el problema permitiendo sólo herencia simple para clases Ejemplo de Interfaz Extendida (1/3) Ejemplo de Interfaz Extendida (2/3) public interface AdministradorRecursos { public void agregarRecurso(String nombre, String driver); public Collection recursosRegistrados (); public interface AdministradorES extends AdministradorEntrada, AdministradorSalida { } public interface AdministradorEntrada extends AdministradorRecursos{ public Collection recursosDirectos (); public void establecerBloqueos(int tipo); } public Collection recursosConBuffer(); } public interface AdministradorSalida extends AdministradorRecursos { public boolean bloquearRecurso(String recurso); } Ejemplo de Interfaz Extendida (3/3) Conflictos de Nombres public class ControladorHDDs implements AdministradorES { public void establecerBloqueos(i n t tipo) {...} l public Collection recursosDirectos() {...} public Collection recursosConBuffer( ) {...} ¿Qué pasa si un mismo nombre se encuentra en más de una interfaz de los supertipos? l public boolean bloquearRecurso(String recurso) {...} public void agregarRecurso(String nombre, String driver) {...} l public Collection recursosRegistrados() {...} } l public class PanelRemoto implements AdministradorES { Si las firmas no son idénticas, es trivial (se sobrecargarán diferentes métodos) Si tienen firma idéntica, entonces la clase tendrá un solo método con esa firma Si las firmas sólo difieren en el tipo de retorno, no se puede implementar la interfaz public void establecerBloqueos(i n t tipo) {...} public Collection recursosConBuffer( ) {...} Para constantes es simple: se selecciona cada una usando nombre de la interfaz public boolean bloquearRecurso(String recurso) {...} l public Collection recursosDirectos() {...} l Ejemplo: X.var, Y.var public void agregarRecurso(String nombre, String driver){...} public Collection recursosRegistrados() {...} } 3 18/04/2004 Interfaces comunes a implementar Modificación de Interfaces l l l l l Una interfaz una vez declarada no debiera ser modificada java.util.Iterator l l Ejemplo: Si se modifica la interfaz ObservadorAcciones agregando un nuevo método, todas las clases que la implementan no son más válidas Por lo tanto, definición de una interfaz requiere diseño cuidadoso l l l public class Proceso implements Comparable { private static i n t lastPid=1; run() java.awt.event.ActionListener l Ejemplo de Implementación de Interfaz (1/2) Vacia! java.lang.Runnable l l compareTo(Object o) java.lang.Cloneable l Problema anterior se soluciona definiendo una subinterfaz con el nuevo método add(), addAll(Collection c), clear(), contains (), ... java.lang.Comparable l l hasNext(), next(), remove() java.util.Collection actionPerformed(ActionEvent e) Ejemplo de Implementación de Interfaz (2/2) class DemoIterador implements java.util.Iterator { private String[] Cartas = { "2","3","4","5","6","7","8","9","10" ,"Sota", "Reina", "Rey","As" } ; private int actual = 0; private int pid; public boolean hasNext() { if (actual == Cartas.length) { return false; else return true; } public Object next() { return (Object) Cartas[actual++]; } public void remove() { throw new UnsupportedOperationException(); } public static void main(String[] args) { DemoIterador i = new DemoIterador (); while (i.hasNext()) { System.out.println(i.next ()); } } private int priority; public Proceso(){ pid=++lastPid ; priority=0; } public i n t getPid (){return p i d;} public void nice( int p){priority+=p; } public i n t compareTo(Object o ) { if(!(o instanceof Proceso)) throw new ClassCastException(); return this.pid - ((Proceso) o).getPid( ) ; } } } Concepto de Paquete 3.6.2 Packages l l Contiene clases, interfaces y subpaquetes que están relacionados Razones para definirlos: l l l l Permiten agrupar interfaces y clases relacionadas Interfaces y clases pueden usar nombres públicos populares sin tener conflictos con otros paquetes Paquetes pueden tener componentes que sólo están disponibles dentro del paquete Facilita la distribución de software 4 18/04/2004 Mecanismo de Definición l l l Ejemplo de uso de Paquete En la primera línea de cada archivo fuente de una clase o interfaz debe aparecer: package <nombre> El nombre del paquete implícitamente se antepone al nombre de la clase o interfaz Ejemplo: miPaquete.miClase Código externo al paquete puede referenciar a tipo internos del paquete de acuerdo a las reglas de control de acceso package personas class Persona { private static private private private int int String int nextID = 0; ID; Nombre; edad = - 1; //... Otros métodos } Se puede referenciar la clase Persona por:personas.Persona Referencias Externas l Una forma es anteponer el nombre del paquete a cada tipo (si existen subpaquetes se puede definir una jerarquía) l l l Ejemplo: cl.utfsm.siga.mipaquete.* Si se usa más de un paquete se pueden producir colisiones de nombre. Para controlar el uso correcto se puede usar: l 1. Anteponer el nombre del paquete en aquellos casos de colisión (e.g. Personas.Persona) l 2. Importar en forma completa un solo paquete y usar nombres completos para los nombres que colisionan Caso real l java.util.Date y java.sql.Date Ejemplo: import Personas.* // OtrasPersonas.Persona se refiere al otro paquete // Persona se refiere ahora a Personas.Persona Control de Acceso a Paquetes l Clases e Interfaces tienen dos accesos: l l Ejemplo: miproyecto.mipaquete.* En grandes organizaciones se acostumbra a usar nombres de dominio de Internet en orden inverso l l Ejemplo import Personas.* // ahora se puede usar la clase Personas sin // anteponer nombre del paquete Si dos paquetes tienen el mismo nombre y requieren ser usados existe un problema Una solución es usar nombres anidados l l l Esta forma es razonable si se usan pocas referencias a tipos del paquete Colisiones de Nombres de Paquetes l l La otra forma es mediante import , lo que permite usar referencias en el código sin anteponer nombre del paquete l l Colisiones de Nombre entre Paquetes l Público. Si se califican con public esta permitido su acceso fuera del paquete Paquete. Sino se declara public, su acceso se restringe dentro del paquete Miembros de clase declarados: l l Sin modificador de acceso son accesibles dentro del paquete, pero fuera de él Miembros no privados son accesibles por cualquier código del paquete (son amistosos) 5 18/04/2004 Recomendaciones l Paquetes se deben definir para clases e interfaces relacionadas l l l Paquetes y directorios Tal agrupación permite una mejor reutilización Permite usar nombres adecuados sin provocar colisiones l l Los paquetes se pueden anidar l l l Permite agrupar paquetes relacionados (e.g. java.lang) Es un asunto organizacional, no de control de acceso Jerarquía típicamente se refleja en la estructura del directorio Paquetes y directorios package usm.lp.agenda; public class Agenda { ... } Paquetes de Java l l l l l ~home/ usm/ l lp/ Los nombres de paquetes condicionan el lugar donde buscar las clases La jerarquía de paquetes debe ser idéntica a la jerarquía de directorios java.lang java.io java.util java.math java.awt java.net agenda/ • • • • • • java.rmi java.applet java.sql java.beans java.security etc. Agenda.java Persona.java .... Extensiones a Java l l l l l l l l l l javax.swing javax.servlet javax.crypto javax.accessibility javax.naming javax.transaction javax.xml javax.sound javax.print etc. Resumen l l l l l l l Definición de Interfaz Herencia Múltiple Conflictos de Nombres Supertipos y Subtipos Implementación de Interfaces Paquetes Control de Componentes de Programas 6