Introduccin a la Programacin Orientada a Objetos Genericidad
Introducción a la Programación Orientada a Objetos Genericidad Departamento de Ciencias e Ingeniería de la Computación UNIVERSIDAD NACIONAL DEL SUR 2019 IPOO 2 cuatrimestre 2019 Sonia Rueda
Los datos de aplicaciones muy diferentes con frecuencia pueden representarse con estructuras a las que se accede con operaciones que no dependen del tipo de las componentes. Una clase genérica encapsula a una estructura cuyo comportamiento es independiente del tipo de las componentes. La genericidad favorece la reusabilidad. IPOO 2 cuatrimestre 2019 Genericidad
La clase Inventario encapsula una colección de componentes de tipo Articulo, representada a través de un arreglo parcialmente ocupado. Las componentes están comprimidas, de modo que si se almacenan cant. Artículos, ocupan las primeras cant. Articulos posiciones del arreglo. Inventario Artículo IPOO 2 cuatrimestre 2019 Genericidad
Genericidad Inventario Articulo T [] Articulo cant. Articulos: entero codigo: entero rubro: entero valor: real anio: entero <<Constructor>> Articulo (c: entero, r: entero, v: entero, a: entero) <<Comandos>> depreciar(p: real) <<Consultas>> equals(a: Articulo ): boolean es. Mayor(a: Articulo ): boolean << Constructores>> Inventario(max: entero) <<Comandos>> insertar (c: Articulo) eliminar (c: Articulo) ordenar() depreciar. Rubro (r: entero, p: real) <<Consultas>> cant. Articulos(): entero esta. Llena(): entero pertenece (c: Articulo): boolean un. Anio(a: entero): Inventario
Inventario(max: entero): crea una colección con capacidad para mantener max artículos. insertar (c: Articulo): asigna el artículo c a la primera posición libre e incrementa cant. Artículos. Requiere c ligado y esta. Llena()== false. eliminar (c: Articulo): busca un artículo equivalente a c, si existe, lo elimina arrastrando los que le siguen una posición y decrementando cant. Artículos depreciar. Rubro (r: entero, p: real): recorre exahustivamente la colección y deprecia cada artículo del rubro r en el porcentaje p. cant. Articulos(): entero: retorna la cantidad de artículos almacenados en la colección esta. Llena(): booleano: retorna true si la cantidad de artículos es igual al tamaño de la colección pertenece (c: Articulo): boolean: retorna true si la colección contiene un elemento equivalente a c. ordenar() reacomoda los elementos de modo quedan ordenados en forma creciente. un. Anio(a: entero): Inventario: retorna una colección con los artículos que corresponden al año a en la colección que recibe el mensaje. IPOO 2 cuatrimestre 2019 Genericidad
La clase Correo encapsula una colección de componentes de tipo Mensaje, representada a través de un arreglo parcialmente ocupado. Las componentes están comprimidas, de modo que si se almacenan cant. Mensajes, ocupan las primeras cant. Mensajes posiciones del arreglo. Correo Mensaje Fecha IPOO 2 cuatrimestre 2019 Genericidad
Genericidad Correo Mensaje T [] Mensaje cant. Mensajes: entero contacto: Contacto fecha: Fecha hora: Hora asunto : String contenido: String << Constructores>> Correo(max: entero) <<Comandos>> insertar (m: Mensaje) eliminar (m: Mensaje) ordenar() <<Consultas>> cant. Mensajes(): entero esta. Llena(): entero pertenece (m: Mensaje): boolean filtro. Asunto(a: String): Correo <<Constructor>> … <<Comandos>> … <<Consultas>> equals(m: Mensaje ): boolean es. Mayor(m: Mensaje ): boolean
Correo(max: entero): crea una colección con capacidad para mantener max mensajes. insertar (c: Mensaje): asigna el mensaje a la primera posición libre e incrementa cant. Mensajes. Requiere c ligado y esta. Llena()== false. eliminar (c: Mensaje): busca un Mensaje equivalente a c, si existe, lo elimina arrastrando los que le siguen una posición y decrementando cant. Mensajes(): entero: retorna la cantidad de Mensajes almacenados en la colección esta. Llena(): booleano: retorna true si la cantidad de Mensajes es igual al tamaño de la colección pertenece (c: Mensaje): boolean: retorna true si la colección contiene un elemento equivalente a c. ordenar() reacomoda los elementos de modo quedan ordenados en forma creciente. filtro. Asunto(a: String): Correo: retorna una colección con los mensajes que corresponden al asunto a en la colección que recibe el mensaje. IPOO 2 cuatrimestre 2019 Genericidad
Genericidad Correo Inventario T [] Mensaje cant. Mensajes: entero T [] Articulo cant. Articulos: entero << Constructores>> Correo(max: entero) <<Comandos>> insertar (m: Mensaje) eliminar (m: Mensaje) ordenar() <<Consultas>> cant. Mensajes(): entero esta. Llena(): entero pertenece (m: Mensaje): boolean filtro. Asunto(a: String): Correo << Constructores>> Inventario(max: entero) <<Comandos>> insertar (c: Articulo) eliminar (c: Articulo) ordenar() depreciar. Rubro (r: entero, p: real) <<Consultas>> cant. Articulos(): entero esta. Llena(): entero pertenece (c: Articulo): boolean un. Anio(a: entero): Inventario
Genericidad Correo Inventario T [] Mensaje cant. Mensajes: entero Correo(max: entero) T [] Articulo cant. Articulos: entero Inventario(max: entero) Coleccion T [] Elemento cant. Elementos: entero Coleccion(max: entero) class Coleccion{ //atributos de instancia protected Elemento [] T; protected int cant. Elementos; //Constructor public Coleccion(int max){ T = new Elemento [max]; cant. Elementos = 0; } …}
Genericidad Coleccion T [] Elemento cant. Elementos: entero Coleccion(max: entero) La clase Coleccion puede usarse para: • Crear objetos de clase Coleccion • Definir clases especializadas que extiendan a Coleccion
Genericidad Correo insertar (m: Mensaje) eliminar (m: Mensaje) cant. Mensajes(): entero esta. Llena(): entero pertenece (m: Mensaje): boolean filtro. Asunto(a: String): Correo Inventario insertar (c: Articulo) eliminar (c: Articulo) depreciar. Rubro (r: entero, p: real) cant. Articulos(): entero esta. Llena(): entero pertenece (c: Articulo): boolean un. Anio(a: entero): Inventario Coleccion insertar (c: Elemento) eliminar (c: Elemento) ordenar() cant. Elementos(): entero esta. Llena(): entero pertenece (c: Elemento): boolean Correo filtro. Asunto(a: String): Correo Inventario depreciar. Rubro (r: entero, p: real) un. Anio(a: entero): Inventario
Genericidad Colección(max: entero): crea una colección con capacidad para mantener max componentes eliminar (c: Elemento): busca un Elemento equivalente a c, si existe, lo elimina arrastrando los que le siguen una posición y decrementando cant. Elementos ordenar() reacomoda los elementos de modo quedan ordenados en forma creciente. cant. Elementos(): entero: retorna la cantidad de Elementos almacenados en la colección esta. Llena(): booleano: retorna true si la cantidad de Elementos es igual al tamaño de la colección pertenece (c: Elemento): boolean: retorna true si la colección contiene un elemento equivalente a c. IPOO 2 cuatrimestre 2019 insertar (c: Elemento): asigna el elemento c a la primera posición libre e incrementa cant. Elementos. Requiere c ligado y esta. Llena()== false.
Genericidad public void insertar (Mensaje m) { /*Inserta un mensaje en la primera posición libre. Requiere que la colección no esté llena y m no nulo*/ T[cant. Mensajes++] = m; } public void insertar (Articulo a) { /*Inserta un elemento en la primera posición libre. Requiere que la colección no esté llena y c no nulo*/ T[cant. Articulos++] = c; } public void insertar (Elemento elem) { /*Inserta un elemento en la primera posición libre. Requiere que la colección no esté llena y elem no nulo*/ T[cant. Elementos++] = elem; }
Genericidad public int cant. Mensajes () { return cant. Mensajes; } public int cant. Articulos() { return cant. Articulos; } public int cant. Elementos() { return cant. Elementos; } La definición de este método genérico solo implica un cambio de nombre.
Genericidad public void eliminar ( Mensaje m){ /* Busca un mensaje equivalente a m en la colección, si lo encuentra arrastra los mensajes que siguen una posición. Requiere m ligado*/ boolean esta = false; int i= 0; while (!esta && i < cant. Mensajes() ) if (T[i]. equals(m)) esta = true; else i++; if (esta) { cant. Mensajes--; arrastrar(i); } }
Genericidad public void eliminar ( Articulo c){ /* Busca un articulo equivalente a c en la colección, si lo encuentra arrastra los articulos que siguen una posición. Requiere c ligado*/ boolean esta = false; int i= 0; while (!esta && i < cant. Articulos() ) if (T [i]. equals(c)) esta = true; else i++; if (esta) { cant. Articulos--; arrastrar(i); } }
Genericidad public void eliminar ( Elemento elem){ /* Busca un elemento equivalente a elem en la colección, si lo encuentra arrastra los elementos que siguen una posición. Requiere elem ligado*/ boolean esta = false; int i= 0; while (!esta && i < cant. Elementos() ) if (T [i]. equals(elem)) esta = true; else i++; if (esta) { cant. Elementos--; arrastrar(i); } } La ligadura dinámica vincula el mensaje equals con el método que corresponda, de acuerdo al tipo dinámico de la variable polimórfica T[i].
Genericidad public void ordenar { /* Reacomoda los elementos en forma creciente aplicando el método de Selección*/ int menor; for (int i=0; i<cant. Elementos()-1; i++){ menor = i; for (int j=i+1; j<cant. Elementos()-1; j++){ if (T[menor]. es. Mayor(T[j]) menor = j; intercambiar(i, menor); } } Cada clase define la implementación de es. Mayor de acuerdo a la relación de orden que convenga.
Genericidad *Elemento *equals (e: Elemento): boolean *es. Mayor (e: Elemento): boolean Mensaje Articulo contacto: Contacto fecha: Fecha hora: Hora asunto : String contenido: String codigo: entero rubro: entero valor: real anio: entero <<Constructor>> … <<Comandos>> … <<Consultas>> equals(e: Elemento ): boolean es. Mayor(e: Elemento ): boolean
Genericidad abstract class Elemento { abstract public boolean equals(Elemento e); abstract public boolean es. Mayor(Elemento e); } interface Elemento { public boolean equals(Elemento e); public boolean es. Mayor(Elemento e); } En este caso también podríamos definir una interface.
Genericidad abstract class Elemento { abstract public boolean equals(Elemento e); abstract public boolean es. Mayor(Elemento e); } class Articulo extends Elemento { //Atributos de instancia … //Constructor … //Comandos … //Consultas public boolean equals(Elemento e){ …} public boolean es. Mayor(Elemento e) { …}; }
Genericidad interface Elemento { public boolean equals(Elemento e); public boolean es. Mayor(Elemento e); } class Articulo implements Elemento { //Atributos de instancia … //Constructor … //Comandos … //Consultas public boolean equals(Elemento e){ …} public boolean es. Mayor(Elemento e) { …}; }
Genericidad class Mensajeria{ private Correo correo; public void gestion. Correo{ Correo correo = new Correo (n); Mensaje m = new Mensaje (…); … correo. insertar(m); … } En la clase Mensajeria el objeto ligado a la variable correo siempre recibe el mensaje insertar con un parámetro de clase Mensaje. } Un objeto de clase Correo puede recibir cualquiera de los mensajes que corresponden a servicios provistos por Coleccion.
Genericidad Las componentes de una instancia de Coleccion tienen tipo estático Elemento, lo cual asegura que están definidos los métodos equals y es. Mayor. Coleccion insertar (c: Elemento) eliminar (c: Elemento) cant. Elementos(): entero esta. Llena(): entero pertenece (c: Articulo): boolean Correo filtro. Asunto(a: String): Correo Inventario depreciar. Rubro (r: entero, p: real) un. Anio(a: entero): Inventario
Genericidad class Correo extends Coleccion { public Correo(int max){ super(max); } public Inventario Filtro. Asunto ( String a){ /* Retorna una colección con los mensajes que corresponden al asunto a en la colección que recibe el mensaje. */ Correo cor= new Correo(cant. Elementos()); for (int i=0; i<cant. Elementos(); i++){ Mensaje sms = (Mensaje) T[i]; if (sms. obtener. Asunto(). equals(a)) cor. insertar(T[i]); } return cor; } } Podemos asegurar que el tipo dinámico de T[i] es Mensaje. En un objeto de clase Correo solo se insertan objetos de clase Mensaje.
Genericidad class Mensajeria{ private Correo correo; public void gestio. Correo{ correo = new Correo (n); Mensaje m = new Mensaje (…); … correo. insertar(m); … String un. Asunto = …; Correo otro = correo. filtrar. Asunto (un. Asunto); } } Un objeto de clase Correo puede recibir cualquiera de los mensajes que corresponden a servicios provistos por su propia clase.
Genericidad Coleccion Colección(max: entero) insertar (c: Elemento) eliminar (c: Elemento) cant. Elementos(): entero esta. Llena(): entero pertenece (c: Articulo): boolean Registro. Signos. Vitales(max: entero) estable(): boolean cant. Alarmas(): entero *Elemento *equals (e: Elemento): boolean *es. Mayor (e: Elemento): boolean Signos. Vitales umbral. Max, umbral. Min : entero maxima, minima : entero equals(e: Elemento ): boolean es. Mayor(e: Elemento ): boolean alarma(): boolean SVDiabetes umbral. Max. G, umbral. Min. G : entero glucemia : entero equals(e: Elemento ): boolean es. Mayor(e: Elemento ): boolean alarma(): boolean
Genericidad class Control. Paciente{ private Registro. Signos. Vitales rs; public void procedimiento. Control{ rs= new Registro. Signos. Vitales (40); Signos. Vitales mañana, tarde; mañana=new SVDiabetes(…); En la clase Control. Paciente el tarde=new SVDiabetes(…); objeto ligado a la variable rs … rs. insertar(mañana); siempre recibe el mensaje rs. insertar(tarde); insertar con un parámetro … if (rs. cant. Alarmas()>2) … que pertenece a la clase } Signos. Vitales. } La clase Control. Paciente es responsable de garantizar que se cumplen los requerimientos asumidos por las clases Signos. Vitales, SVDiabetes y Registro. Signos. Vitales.
Genericidad class Registro. Signos. Vitales extends Coleccion { public Registro. Signos. Vitales(int max){ super(max); } public boolean cant. Alarmas(){ /* Computa la cantidad de registros que indican alarma en la temperatura, la presión o la glucemia en el caso de pacientes diabéticos a los que se les realiza esta medición*/ int cant=0; for (int i=0; i<cant. Elementos(); i++){ Signos. Vitales sv= (Signos. Vitales) T[i]; if (sv. alarma()) cant++; } return cant; } } Como solo insertamos objetos que pertenecen a la clase Signos. Vitales, podemos asegurar que T[i] mantiene una referencia a un objeto de clase Signos. Vitales.
Genericidad La clase Coleccion es genérica, permite factorizar el comportamiento compartido definiendo un patrón general. Las clases Correo, Inventario y Registro. Signos. Vitales extienden a Coleccion con servicios específicos. En un objeto de clase Correo solo tiene sentido insertar objetos de clase Mensaje. Si desde la clase Mensajeria por error se insertaran objetos de clase Articulo en un objeto de clase Correo, la ejecución del método filtrar. Asunto, por ejemplo, provocaría un error. Si usamos instance. Of podemos prevenir la terminación anormal, pero el error persiste, porque se trata de un error en la aplicación.
Genericidad Estamos modelando genericidad usando herencia. En las materias que siguen se presenta un mecanismo para definir clases genéricas a partir de polimorfismo paramétrico. Java brinda recursos limitados para soportar este concepto.
- Slides: 32