Download Tema 3. Paradigma Orientado a Objetos
Document related concepts
no text concepts found
Transcript
Lenguajes de Programación Tema 3. Paradigma Orientado a Objetos Pedro García López pgarcia@etse.urv.es/ Copyright • © University Rovira i Virgili • Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; A copy of the license is available at: • http://www.fsf.org/licenses/fdl.html Indice • • • • Introducción Paradigma Orientado a Objetos Estudio de caso: Java Conclusiones Paradigma Orientado a Objetos • • • • Conceptos generales Clases y Objetos Herencia Polimorfismo Problemas en la creación del software ¿Hay crisis del software? • Gran complejidad – Número de estados posibles es muy elevado – Conexiones entre entidades – Complejidad arbitraria que surge de instituciones humanas • • • • Sujeto a continuos cambios No tiene representación gráfica Especificación de requisitos Comunicación del equipo Calidad del Software Factores Externos • • • • • Corrección Robustez Extensibilidad Reutilización Compatibilidad Factores Internos • Modularidad • Legibilidad • • • • Eficiencia Portabilidad Facilidad de uso Funcionalidad Mantenimiento del software • • • • Parte noble: MODIFICACION Parte no noble: DEPURACION Se le dedica el 70 % del coste del software Distribución coste según [Lientz79]: – – – – – Cambios solicitados por los usuarios (41.8%) Cambios en los formatos de los datos (17.4%) Cambios de emergencia (12.4%) Depuración rutinaria (9%) Costes de documentación (5.5%) Mantenimiento del software • Conclusiones del estudio: – Ausencia de extensibilidad – Estructura física de los datos dispersa por muchas partes del sistema – No se hace documentación a posteriori – Cuando el sistema funciona no se buscan mejoras en eficiencia. En los Sistemas Software interesa ... Acoplamiento mínimo: • Numero de conexiones sea mínimo • Flujo de información sea mínimo • Comunicaciones explícitas Cohesión interna: • Cohesión de datos • Cohesión funcional Modulo A Modulo B Modulo C Modulo A Modulo B Modulo C Reutilización del software • ¿Por qué el software no es como el hardware? • ¿Por qué cada nuevo proyecto software arranca de la nada? Librerías de software Software-IC Repetición en el desarrollo del software • ¿Cuántas veces en los últimos 6 meses has escrito código para buscar un elemento en una colección? • Naturaleza repetitiva de la programación (ordenar, buscar, recorrer, ...) • ¿Por qué no es frecuente? – Dificultades técnicas y no técnicas Dificultades técnicas • Diseñar código reutilizable es difícil. • Hacemos las mismas cosas pero no de la misma forma. • Difícil captura de las similitudes. • Permitir adaptación Ejemplo FUNCTION buscar (x: Elemento; c: Coleccion): BOOLEAN VAR pos : Posicion; BEGIN pos:= Comenzar (x,c); WHILE not Completa (pos,c) and not Encontrado (pos, x, c) DO pos:= Siguiente (pos, x, c); buscar:= not Completa (pos,c); END; Rutina genérica para “búsqueda en una colección” Requisitos de los módulos para facilitar la reutilización FUNCTION buscar (x: Elemento; c: Coleccion): BOOLEAN VAR pos : Posicion; BEGIN pos:= Comenzar (x,c); WHILE not Completa (pos,c) and not Encontrado (pos, x, c) DO pos:= Siguiente (pos, x, c); buscar:= not Completa (pos,c); END; 1. Variación en tipos Aplicable a diferentes tipos de elementos x: Elemento Requerimientos de los módulos para facilitar la reutilización FUNCTION buscar (x: Elemento; c: Coleccion): BOOLEAN VAR pos : Posicion; BEGIN pos:= Comenzar (x,c); WHILE not Completa (pos,c) and not Encontrado (pos, x, c) DO pos:= Siguiente (pos, x, c); buscar:= not Completa (pos,c); END; 2. Variación en estructuras de datos y algoritmos El tipo Coleccion puede estar implementado de diferentes formas y Siguiente(pos,x,c) puede estar ligado a diferentes rutinas: FAMILIAS DE MODULOS relacionados Requerimientos de los módulos para facilitar la reutilización FUNCTION buscar (x: Elemento; c: Coleccion): BOOLEAN VAR pos : Posicion; BEGIN pos:= Comenzar (x,c); WHILE not Completa (pos,c) and not Encontrado (pos, x, c) DO pos:= Siguiente (pos, x, c); buscar:= not Completa (pos,c); END; 3. Independencia de la representación Se puede usar una operación sin conocer su implementación siguiente(pos,x,c), comenzar(x,c), encontrado(pos,c), completa(pos,c) Independencia de la representación Alternativa: if “c es de tipo A” then “aplicar algoritmo de búsqueda A” elseif “c es de tipo B” then “aplicar algoritmo de búsqueda B” elseif … • Este código sería incluido en: – Un único módulo: Grande y sujeto a constantes cambios – Código cliente: Dificulta la extensibilidad Requerimientos de los módulos para facilitar la reutilización. FUNCTION buscar (x: Elemento; c: Coleccion): BOOLEAN VAR pos : Posicion; BEGIN pos:= Comenzar (x,c); WHILE not Completa (pos,c) and not Encontrado (pos, x, c) DO pos:= Siguiente (pos, x, c); buscar:= not Completa (pos,c); END; 4. Factorizar comportamientos comunes dentro de una familia de implementaciones 5. Rutinas relacionadas Ejemplo: Factorizar comportamientos comunes Tabla Secuencial Lista Conjunto Array Fichero Secuencial • La operación “búsqueda” se escribe una sola vez. FUNCTION busqueda (x: elemento; t:Secuencia): BOOLEAN BEGIN Comenzar; WHILE not Completa and not Encontrado(x) DO Avanzar; busqueda:=not Completa; END; ARRAY Comenzar Avanzar Completa Encontrado i:=1 i:=i+1 i>tamaño t[i] = x LISTA ENLAZADA l:=cabeza l:=l^.next l=nil l^.item = x FICHERO SECUENCIAL reset read eof f^= x Una nueva variante sólo tiene que especificar cómo implementar estas cuatro rutinas Estructuras modulares tradicionales • Rutinas • Paquetes o Módulos ¿Por qué no son suficientes? Posibles soluciones para darles flexibilidad: • Sobrecarga • Genericidad ¿cubre los requisitos de módulos reutilizables? Rutinas • Unidad de software que puede llamar a otras unidades para ejecutar un cierto algoritmo. • Enfoque de reutilización: librerías de rutinas • Adecuadas en áreas donde pueden ser identificado un conjunto de problemas individuales con las siguientes limitaciones: 1. Admiten especificación simple: pequeño conjunto de parámetros. 2. No estén implicadas estructuras de datos complejas. 3. Problemas claramente diferenciados. Limitaciones de las rutinas • Soluciones para: "Búsqueda en una colección secuencial”: 1) Una rutina: • "CASE" enorme. • Muchos argumentos. 2) Conjunto de rutinas: • Rutinas muy similares ( factorizar comportamiento) • Cliente debe buscar en un laberinto de rutinas. Conclusión: Un módulo reutilizable debe estar abierto a la adaptación y, la única forma de adaptación de una rutina es pasarle diferentes argumentos. Las rutinas no son suficientemente flexibles Paquetes/Módulos • Son unidades de descomposición de software que: – Cumplen el principio de Unidad Lingüística Modular – Contienen variables y rutinas relacionadas = características del `paquete – Admiten la Ocultación de la Información (módulos abstractos) – Permite la implementación de tipos definidos por el programador • Los módulos sólo resuelven ”rutinas relacionadas” – facilita depuración y cambio al proveedor – es más fácil para los clientes encontrar y usar los servicios de los módulos Ejemplo: Paquetes/Módulos Package TablaEnteros; type ArbolBinEnteros record info: Integer izq, der: ArbolBinEnteros end; PAQUETE DECLARACIÓN DE TIPO new: ArbolBinEnteros begin … end; OPERACIONES añadir(t:ArbolBinEnteros; x: Integer) begin … end; SOBRE EL TIPO existe(t:ArbolBinEnteros; x: Integer): Boolean begin .. end …. end Sobrecarga • Identificador con más de un significado. • Ejemplo: Sobrecarga de rutinas FUNCTION Búsqueda (x:Cuenta; t: ListaCuentas): Boolean; FUNCTION Búsqueda (x:CHAR; t: ARRAY [CHAR]): Boolean; FUNCTION Búsqueda (x:REAL; t: ARRAY[REAL]): Boolean; • Facilidad sintáctica orientada a los clientes. • Permite escribir el mismo código cliente usando diferentes implementaciones de cierto concepto. ¿Qué nos proporciona la sobrecarga? • ¿ Resuelve “Variación en estructuras de datos y algoritmos”? • ¿Resuelve “Independencia de la representación”? • En cada invocación “Busqueda(x,t)” cliente y compilador saben de que versión se trata. • “Independencia en la representación” exige poder escribir “Busqueda(x,t)” significando: “Busca x en t usando el algoritmo adecuado, cualesquiera que sea la clase de colección ligada a t en tiempo de ejecución” Genericidad • Posibilidad de definir módulos parametrizados, cuyos parámetros representan tipos. • Facilidad orientada a los creadores de módulos permite escribir el mismo código cuando se usa la misma implementación de cierto concepto, aplicado a diferentes tipos de objetos” Ej: Array [T], Lista[T] • Los módulos cliente deben instanciar el módulo genérico Ej: Array [Real], Lista[Figura], • Resuelve “variación en tipos” Ejemplo de Genericidad Package Tabla[T]; type ArbolBinario record info: T izq, der: ArbolBinEnteros end; new: ArbolBinario begin … end; añadir(t:ArbolBinario; x: T) begin … end; existe(t:ArbolBinario; x: T): Boolean begin .. end …. end Conclusión • La genericidad resuelve: Variación en tipos. • Los paquetes/modulos resuelve: Rutinas relacionadas. • No se resuelve: Variación en estructuras de datos y algoritmos. Independencia de la representación. Capturar similitudes entre un subgrupo de un conjunto de posibles implementaciones. Descomposición Funcional A B Secuencia D C Condicional Bucle E F G H Inconvenientes de la Descomposición Funcional • Función principal: “Cima del sistema” – El “programa principal” es una propiedad volátil – Sistemas reales no tienen “cima” – Mejor la visión de un “conjunto de servicios” • Centrado en la interfaz – Primera pregunta: ¿Que hará el sistema? – La arquitectura del software debe basarse en propiedades más profundas. • Ordenación temporal prematura Inconvenientes de la Descomposición Funcional • No favorece la reutilización – Se desarrollan elementos software para satisfacer necesidades específicas de otro elemento del nivel superior. – “Cultura del proyecto actual” • Las estructuras de datos son descuidadas – Funciones y datos deben jugar un papel complementario • Cuando un sistema evoluciona los datos son más estables que los procesos. Ventajas de la Descomposición Funcional • Técnica simple, fácil de aplicar • Util para pequeños programas y describir algoritmos. • Buena para documentar diseños. • Facilita desarrollo sistemático de sistemas • Adecuada para dominar la complejidad Descomposición basada en objetos • Los objetos son más estables que las funciones cuando el sistema evoluciona (Extensibilidad). • Tipos de objetos equipados con las operaciones asociadas (Reutilización). • El diseñador lista las operaciones aplicables a cierto tipo de objetos, especificando su efecto. • Se retrasa todo lo posible el orden en que se ejecutan las operaciones. Desarrollo software OO 1. Encontrar tipos de objetos relevantes 2. Encontrar operaciones para tipos de objetos 3. Describir tipos de objetos 4. Encontrar relaciones entre objetos 5. Usar tipos de objetos para estructurar software Conceptos Clave POO • • • • • • • • • • • Clase y Objeto Clase: Atributos y métodos Creación de clases: constructores e instanciación Invocación de métodos Atributos y métodos de clase Ocultación de información Tipos referencia, asignación, aliasing y copia de objetos Concepto de Metaclase Relaciones entre clases: clientela y herencia Tipos de herencia Polimorfismo y ligadura dinámica Clases y Objetos Una clase es un módulo y un tipo de dato: • Módulo (concepto sintáctico) – Mecanismo para organizar el software (sintáctico) – Encapsula componentes software • Tipo (concepto semántico) – Mecanismo de definición de nuevos tipos de datos: describe una estructura de datos (objetos) para representar valores de un dominio y las operaciones aplicables. Combinación módulo-tipo “Los servicios proporcionados por una clase, vista como un módulo, son precisamente las operaciones disponibles sobre las instancias de la clase, vista como un tipo”. • Como cada módulo es un tipo, cada operación del módulo es relativa a cierta instancia del tipo TAD y Clase Teoría TAD {Operaciones: Sintaxis y Semántica} Software Clase {Elegir representación e implementar operaciones} Clases: Ejemplo • Al modelar un banco, encontramos objetos “cuenta”. • Todos los objetos “cuenta” tienen unas propiedades comunes: – saldo, titular, código, reintegro, ingreso, … • Definimos una clase Cuenta. • Clases del dominio y clases de diseño/implementación Componentes de un clase • Atributos – Determinan una estructura de almacenamiento para cada objeto de la clase • Rutinas (Métodos) – Operaciones aplicables a los objetos – Único modo de acceder a los atributos Ejemplo: Al modelar un banco, encontramos objetos “cuenta”. Todos los objetos “cuenta” tienen propiedades comunes: • atributos: saldo, titular, ... • operaciones: reintegro, ingreso, … Definimos una clase CUENTA. Cada objeto es instancia de una clase Estructura de datos Código Objeto Cuenta Objeto Cuenta Clase Cuenta Instanciación Objeto Cuenta Objeto Cuenta Cuenta oc oc = new Cuenta() Cada objeto es instancia directa de una clase. Una clase es una factoría de objetos Constructores (C++ y Java) • Realizan la inicialización de un objeto tras la creación. • Un constructor – procedimiento especial con el mismo nombre que la clase. – Se debe invocar cuando se crea un objeto de la clase con el operador new – En C++ también cuando se declara una variable. – Pueden tener modificadores de acceso Mensajes • Mecanismo básico de la computación OO. • Invocación de la aplicación de un método sobre un objeto. • La modificación o consulta del estado de un objeto se realiza mediante mensajes. • Formado por tres partes – Objeto receptor – Selector o identificador del método a aplicar – Argumentos Semántica mensajes • Sea el mensaje x.f, su significado es: “Aplicar el método f sobre el receptor x, efectuando el paso de parámetros” ¡NO CONFUNDIR CON LA INVOCACIÓN DE UN PROCEDIMIENTO! Variables y métodos de Clase • Compartida por todas las instancias de una clase. • Registrar valor común a todas las instancias • Ejemplos para una clase Cuenta: – Interés, Coste tarjeta, Último código asignado • ¿Cuándo se inicializa? • Puede ser accedida por métodos de instancia y de clase • Los métodos de clase no deberían acceder a variables de instancia Clases y Ocultación de Información • Ocultamiento información importante para conseguir arquitecturas flexibles y coherentes. • Interface vs. Implementación: – Un cliente sólo conoce la interface. – Sólo los métodos de la clase deberían poder acceder a sus atributos. • Cada lenguaje OO (Eiffel, C++, Java, Smalltalk) presenta diferencias en cuanto al ocultamiento de información. Tipos referencia • Los posibles valores de una entidad (atributo, parámetro, …) son referencias a objetos potenciales que pueden ser creados en tiempo de ejecución a través, siempre, de instrucciones de creación explícitas. • Una referencia puede encontrarse en uno de dos estados posibles – No ligada: Void (Eiffel) o null (Java) – Ligada a un objeto • Las referencias son “punteros domesticados”. • Void es un estado (null es un literal) mientras que “nil” (en Pascal) o “null” (en C) son valores de tipo puntero. Ventajas de los tipos referencia • Más eficiente para manejar objetos complejos. • Soporte para definir estructuras de datos recursivas. • Soporte del polimorfismo. • Los objetos son creados cuando son necesarios. • Permite la compartición de un objeto (integridad semántica). • DESVENTAJA: “Aliasing” Asignación ob oa oa:= ob oa ob La asignación no implica copia de valores sino de referencias ¡Cuidado con el Aliasing! Solución: Copia de objetos • Copia superficial – Se copian los valores de cada campo del objeto origen oy en el objeto destino ox; ox y oy comparten referencias. – Soportada por defecto y puede redefinirse para una clase concreta. • Copia profunda – Se crea un objeto con una estructura idéntica al objeto origen. – No hay compartición de referencias – No suele ser soportada por defecto Metaclases • Una clase puede ser considerada un objeto: – ¿Cuál es su clase? • Metaclase – Clase que describe clases, sus instancias son clases. – Propiedades: lista de atributos, lista de variables de clase, lista de métodos, lista de métodos de clase. • Java y Smalltalk tienen metaclases • Útil en programación avanzada, cuando se manejan entidades software, p.e. depuradores, inspectores, browsers,.. Relaciones entre clases • Clientela Una clase A es cliente de una clase B, si A contiene una declaración en la que se establezca que cierta entidad (atributo, parámetro, variable local) e es de tipo B (e:B) CUENTA Ejemplo: • Herencia titular: Persona PERSONA “Cuenta es cliente de Persona” Una clase es una versión especializada de otra existente Cuenta Ejemplo: CuentaAhorro CuentaCorriente Herencia La herencia organiza las clases en una estructura jerárquica: Jerarquías de clases Ejemplos: PUBLICACION LIBRO LIBRO_TEXTO REVISTA INVESTIGACION MAGAZINE FIGURA POLIGONO RECTANGULO • No es tan solo un mecanismo para compartir código. • Consistente con el sistema de tipos del lenguaje CIRCULO Herencia • Puede existir una clase “raíz” en la jerarquía de la cual heredan las demás directa o indirectamente. • Incluye todas las características comunes a todas las clases Eiffel: Smalltalk: Java: C++: clase ANY clase Object clase Object no existe Herencia Si B hereda de A entonces B incorpora la estructura (atributos) y comportamiento (métodos) de la clase A, pero puede incluir adaptaciones: -B puede añadir nuevos atributos -B puede añadir nuevos métodos •Refinamiento: Extender el uso original -B puede REDEFINIR métodos •Reemplazo: Mejorar la implementación -B puede renombrar atributos o métodos - B puede implementar un método diferido en A … Adaptaciones dependientes del lenguaje (Redefinición disponible en cualquier LOO) Polimorfismo • Es restringido por la herencia • Importante para escribir código genérico • Sea las declaraciones: ox: X; rutina1 (oy:Y) – En un lenguaje con monomorfismo (Pascal, Ada, ..) en t.e. ox y oy denotarán valores de los tipos X e Y, respectivamente. – En un lenguaje con polimorfismo (Eiffel, C++, ..) en t.e. ox y oy podrán estar asociados a objetos de varios tipos diferentes: tipo estático vs. tipo dinámico Tipo estático y tipo dinámico • Tipo estático: – Tipo asociado en la declaración • Tipo dinámico: – Tipo correspondiente a la clase del objeto conectado a la entidad en tiempo de ejecución • Conjunto de tipos dinámicos: – Conjunto de posibles tipos dinámicos de una entidad Ejemplo: A B D C E F oa: A; ob: B; oc; C; te(oa) = A ctd(oa) = {A,B,C,D,E,F} te(ob) = B ctd(ob) = {B, D, E} te(oc) = C ctd(oc) = {C,F} p (antes) (después) Conexión polimorfa (POLIGONO) r p:POLIGONO; r:RECTANGULO (RECTANGULO) • Cuando el origen y el destino tiene tipos diferentes: a) asignación: p := r; polimorfa -- p es una entidad b) paso de parámetros: f (p:POLIGONO) is do ... end polimorfa -- f es una rutina • Sólo se permite para entidades destino de tipo referencia Tipos de polimorfismo • Real – Paramétrico (“lista de T”) – Inclusión: • Basado en la herencia • una función y varias interpretaciones diferentes • Aparente – Sobrecarga • varias funciones todas con el mismo nombre Ejemplo polimorfismo paramétrico: long (l:lista): integer if l=nil then long:=1 else long:= 1 + long(cola(l)) Sobrecarga • Es el nombre de la función lo que es polimórfico • Se resuelve en tiempo de compilación, según la signatura de la rutina. • No es necesario que exista similitud semántica. • En los lenguajes OO puede existir sobrecarga – dentro de una clase – entre clases no relacionadas (es fundamental) Polimorfismo y código genérico • Estructuras de datos polimórficas: Pueden contener instancias de una jerarquía de clases • Ejemplo: p: POLIGONO; r: RECTANGULO; c: CIRCULO; t:TRIANGULO; !!p; !!r; !!c; !!t; fig.put (p,1); fig.put (r,2); fig.put (c,3); fig.put (t,4); ... fig: ARRAY [FIGURA] fig 1 2 3 4 Genericidad • ¿Cómo escribir una clase que represente una estructura de datos y que sea posible almacenar objetos de cualquier tipo? Pila-Enteros Pila_Libros Pila de ? Pila_Figuras …. • Necesidad de reconciliar reutilización con el uso de un lenguaje tipado. Herencia ColeccionEntero ColeccionTarea ListaEntero GrafoTarea ListaCircularEntero RedTarea class ListaEntero inherit ColeccionEntero feature numElements: Integer is do .. añadir (i: Integer, v:Integer) is do .. iesimo (i:Integer): Integer is do .. buscar (v:Integer): Boolean is do .. ... end ¿Cómo asociar a v un tipo pero sin hacer que la clase sea dependiente del tipo de objeto almacenado? Genericidad Coleccion [G] Lista [G] ListaCircular [G] class Lista [G] feature numElements. Integer is do .. añadir (i: Integer, v:G) is do .. iesimo (i:Integer): G is do .. buscar (v:G): Boolean is do .. ... end miLista1: Lista [Integer] miLista2: Lista [Punto] Genericidad • Posibilidad de parametrizar las clases; los parámetros son tipos de datos. • Facilidad útil para las clases que representan estructuras de datos generales: TIPO BASE ES UN PARAMETRO class ARRAY [G], class PILA [G], [G], ... class LISTA • Orientada a los creadores de clases Estudio de caso: Java Lenguaje: • Simple • Orientado a Objetos • Robusto • Arquitectura-neutral (portable) • Moderno – librerias (+ APIs) – excepciones – (...) Hola Mundo /* * Example HelloWorld * Prints the message "Hello, World!“ */ public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, world.”); } } Palabras reservadas abstract boolean break byte byvalue case cast catch char class const continue default do double else extends false final finally float for future generic goto if implements import inner instanceof int interface long native new null operator outer package private protected public rest return short static super switch synchronized this throw throws transient true try var void volatile while Tipos Simples Tipos Simples Tamaño Valor Mínimo Valor Màximo Tipos Wrapper boolean 1-bit - - Boolean char 16-bit Unicode 0 Unicode 216-1 Character byte 8-bit -128 +127 Byte short 16-bit -215 +215-1 Short int 32-bit -231 +231-1 Integer long 64-bit -263 +263-1 Long float 32-bit IEE754 IEE754 Float double 64-bit IEE754 IEE754 Double void - - - Void Bloques Comandos y secuenciadores if (expressBool) { .... } else { .... } switch (selector) { case valor1: instrucció1; break; selector: case valor2: ........... char,byte,short,int ... default: instruccióN; } Comandos y Secuenciadores • Bucles FOR: for (<inicialització>; <continuar si ...>;<increment>) for (int i=0; i<10; i++) {...} • Bucles DO-WHILE do { ... } while (expressioBooleana); • Bucles WHILE while (expressioBooleana) { ... } Clases en Java • Lenguaje tipado estáticamente • Legible • No separación en fichero interfaz e implementación. • Lenguaje interpretado: Máquina Virtual Java • Atributos y variables de clase • Métodos de instancia y de clase • Incluye metaclases (Reflexión) Ejemplo: Cuenta class Cuenta { private String private int private int private int[] titular; saldo; codigo; ultOper; private static int ultimoCodigo = 0; public static int nuevoCodigo () {return ++ultimoCodigo;} public Cuenta (String quien) { saldo=0; titular=quien; codigo = nuevoCodigo(); ultOper = new int[100];} public void reintegro (int suma) { if (puedoSacar(suma)) saldo=saldo-suma;}; public void ingreso (int suma) { saldo=saldo+suma;} public int getSaldo () { return saldo; } private boolean puedoSacar(int suma) {return (saldo >=suma);} } Creación de Objetos • Acceso a las variables de instancia de la clase mediante métodos de instancia (set y get). Cuenta c = new Cuenta (“pedro”); c.reintegro(10000); c.ingreso(20000); int x = c.getSaldo(); “ Propiedades de clase: static class Cuenta { private String titular; public static int interes=3; public int setInteres(int cantidadPts) { interes= cantidadPts } ¿ Que ocurre ? Propiedades de clase • No podemos acceder desde variables de clase a variables de instancia. // Método de clase public static int setInteres(int cantidadPts) { interes= cantidadPts } Propiedades de clase public class HelloWorld { public static void main(String[] args) { Cuenta.setInteres(12); Math.sqrt(9); } } Las propiedades de clase son válidas para todos los objetos de la clase. Clases Java y Ocultación de Información • “package” – accesible por las clases del paquete, no accesible a los clientes del paquete • public – accesible por todas las clases • private – sólo accesible por los métodos de la clase • protected – accesible por las clases del paquete y por las subclases Visibilidad The class itself Clases del mismo paquete Subclases de otro paquete No-subclases de otro paquete packag public protected e Si Si Si private Si Si Si Si No Si Si No No Si No No No Asignación • Un objeto asociado a una variable cambia cuando se evalúa una expresión de asignación. variable = expresión • Ejemplos: c1:=new Cuenta(); saldo := saldo - cantidadPtas. s:= c1.saldo(); rect := new Rectangulo(punto1, punto2); miObjeto:= otroObjeto; • El operador := no hace una copia del objeto Asignación y cloning Point p = new Point (1,1); Point p2 = p; p2.setLocation(120,120); //Aliasing System.out.println("Valor de p:" + p.getX()); System.out.println("Valor de p2:" + p2.getX()); Point p3 = (Point)p.clone(); p3.setLocation(40,40); System.out.println("Valor de p:" + p.getX()); System.out.println("Valor de p3:" + p3.getX()); Copia en Java • La clase Object incluye el método protected Object clone( ) {..} ..} que implementa una copia superficial. • Para poder clonar objetos de una clase se debe – Declarar que implementa la interfaz Cloneable – Redefinir y hacer público el método clone() – Dejar la versión original (copia superficial) o bien hacer una copia de mayor profundidad. Paso de Parámetros class PassByValue { public static void modifyPoint(Point pt, int j) { pt.setLocation(5,5); j = 15; } public static void main(String args[]) { Point p = new Point(0,0); int i = 10; modifyPoint(p, i); }} //1 //2 //3 Concepto de Metaclase: RTTI • Run Time Type Identification • Object – Class getClass() • Class – – – – getFields getMethods getName (...) Agrupación de clases: Package • • • • package pedro.utils; import pedro.utils.*; import pedro.*; // No es jerárquico import pedro.utils.Cosa; Paquetes Java – – – – – – java.lang --- general java.awt --- GUI java.io --- I/O java.util --- utilities java.applet --- applet java.net --- networking Tipos Wrapper int a =1; int b= 2*3; Integer awrap = new Integer(a); int x = awrap.intValue(); int y = Integer.parseInt("123"); String z = String.valueOf(y); Arrays: Tipo parametrizable int lista [] = new int[100]; lista[0]=1; for (int i=0;i<lista.length;i++) lista[i]=0; int lista[] = {1,2,3,4}; Perro lista2 = new Perro[100]; lista2[0] = new Perro (); Object lista3 = new Object [100][100]; Relaciones entre clases Composicíón: Tiene - Un Student -name : String * -gpa : float * Faculty 1 1 Address -streetAddress : String -city : String -state : String -zipCode : String Relaciones entre clases Herencia: Es -Un Student GraduateStudent MasterStudent PhDStudent UndergraduateStudent Clases abstractas • Algún método no se implementa • No podemos instanciar una clase abstracta • La clase abstracta puede tener métodos no abstractos • La clase abstracta debe ser heredada. public abstract class Figura { public abstract dibujar(); } Herencia en Java • public class X extends Y {...} Sintaxis de clase [ ClassModifiers ] class ClassName [ extends SuperClass ] [ implements Interface1, Interface2 ...] { ClassMemberDeclarations } • La clase Object • this y super Polimorfismo Animal a = new Animal(); Perro p; a = p; Object x; Perro p = new Perro(); x = p; Polimorfismo y castings Vector list = new Vector(); String s = “lala”; Perro p = new Perro(); list.add(p); list.add(s); Object x = list.elementAt(0); Perro p2 = (Perro)list.elementAt(0); Polimorfismo y ligadura dinámica • Java es un lenguaje tipado estáticamente • La ligadura de un mensaje a un método concreto se realiza en tiempo de ejecución • ¿Qué versión de perímetro se ejecuta en cada mensaje? f= new Poligono (); f.perimetro(); r = new Rectangulo(); r.perimetro(); f=r; f.perimetro(); {i} {ii} {iii} Interfaces • Son clases en las que todos las propiedades son estáticas y finales y todos los métodos son abstractos. interface Persona interface Perro { { public void habla(); } public void ladra(); } Interfaces y herencia public class Mutante implements Persona, Perro { public void habla() { System.out.println(“Soy una persona”); } public void ladra() { } } System.out.println(“GUAU”); Interfaces y polimorfismo Mutante m = new Mutante(); Persona p = m; p.habla(); Perro p = m; m.ladra(); Interfaces class Prueba { public static void ladra (Perro p) { p.ladra(); { public static void habla(Persona p) { p.habla() } Interfaces Mutante m = new Mutante(); Prueba.habla(m); Prueba.ladra(m); Ejemplo código genérico java.util.Collection Collection AbstractCollection AbstractList Vector Stack ArrayList AbstractSet LinkedList ArraySet HashSet Ejemplo: código genérico • • • • • • • • • • • • boolean add(Object) boolean addAll(Collection) void clear() boolean contains(Object) boolean containsAll(Collection) boolean isEmpty() Iterator iterator() boolean remove(Object) boolean removeAll(Collection) boolean retainAll(Collection) int size() Object[] toArray() Iteradores • • • • boolean hasNext() Object next() void remove() [implementación opcional] Por ejemplo: public void escribir (Collection c) { for (Iterator it=c.iterator(); it.hasnext();) { System.out.println(it.next()); } } Genericidad y Java • Java no posee genericidad (hasta el Jdk1.5) • Necesidad de declaraciones de tipo Object • Problemas: – Necesidad de conversiones de tipo – No se asegura homogeneidad • Incluye genericidad para arrays private Cuenta[ ] cuentas = new Cuenta[100] private int[ ] valores = new int [4] Estructuras de datos polimorfas • Contiene objetos de diferentes clases • Ejemplo: Array con cualquier variante de Figura Figura conjFig = new Figura[10]; p= new Poligono(); r = new Rectangulo(); c = new Circulo();. t = new Triangulo(); conjFig[0]=p; conjFig[0]=r; conjFig[0]=c; conjFig[0]=t; conjFig 1 2 3 4 Estructuras polimorfas y código genérico public void dibujarFiguras() { for (int i=0;i<conjFig.length;i++) conjFig[i].dibujar(); } Genericidad Restringida • Es posible restringir las clases a las que se puede instanciar el parámetro genérico formal de una clase genérica. class C [G -> R] • Sólo es posible instanciar G con descendientes de la clase R. • Ejemplos: VECTOR [G - > NUMERIC] DICTIONARY [G, H - > COMPARABLE] ORDENACION [G - > COMPARABLE] • Permite aplicar operaciones sobre entidades cuyo tipo es un parámetro genérico formal. Genericidad en Java (JDK1.5) • Basado en las templates de C++ • Se han rediseñado las colecciones de Java para acomodar el código genérico • Se han rediseñado los iteradores para hacerlos más sencillos • Permite genericidad restringida Ejemplos genericidad Nuevo iterador: for (Tipo elem: colección) Ejemplos genericidad Enumerados (JDK1.5) Static Import (JDK1.5) Excepciones Java • “Proporcionan una manera limpia de comprobar errores sin complicar el código” • “Proporcionan, además, un mecanismo para señalar directamente los errores sin necesidad de usar indicadores (atributos, parámetros)”. • “Son lanzadas cuando se detectan situaciones imprevistas de error”. Excepciones Java BufferedReader br; int codigoProducto = Integer.parseInt (br.readLine() ) • Puede suceder algo inesperado como que: – br represente un fichero sobre un disco flexible que se ha extraído – br represente una conexión en red y se produzca una caída de la red – br represente un fichero en mal estado sobre el disco duro – el usuario introduzca un carácter no numérico – el usuario introduce un código numérico incorrecto Situaciones que deben ser manejadas por excepciones 119 Excepciones Java • Las excepciones son objetos. • Hay dos tipos: – Comprobadas – No comprobadas • Necesidad de definir subclases de Exception o RunTimeException. Jerarquía de Tipos de Excepciones Java Object Throwable Error Exception RunTimeException No comprobadas Comprobadas Excepciones Comprobadas • Subclases de Exception • Un método que lance una excepción comprobada, debe especificarlo en su signatura. • El código que invoca un método que puede lanzar una excepción comprobada debe manejarla mediante una cláusula try-catch. • Situaciones comprobadas por el compilador Excepciones No Comprobadas • Subclases de RuntimeException • Un método puede lanzar una excepción no comprobada, sin especificarlo en su signatura. • El código que invoca un método que puede lanzar una excepción no comprobada no debe manejarla. • Es recomendable listar todas las excepciones en la signatura para facilitar su uso. ¿Cómo elegimos si una nueva excepción es comprobada o no comprobada? 123 Uso de Excepciones Comprobadas public class ClaveNoExiste extends Exception { public ClaveNoExiste() { super(); } } // método en TablaHash public void cambiarValor (String clave, Object valor) throws ClaveNoExiste { if (obtener(clave) == null) throw new ClaveNoExiste (); … } TablaHash unaTabla; ... try { unaTabla.cambiarValor(s,v);} catch (ClaveNoExiste e) {...} finally {...} 124 Excepciones Comprobadas ¿Qué puede hacer el cliente de un método que lanza una excepción comprobada? 1) Capturarla y manejarla 2) Capturarla y asociarla a una de las excepciones declaradas en el método. 3) Declararla en la cláusula throws y no manejarla, con lo que se propaga al método que lo invocó. Excepciones No Comprobadas ¿Qué puede hacer el cliente de un método que lanza una excepción no comprobada? 1) Si no la captura se propaga al método que lo invocó. 2) También puede capturarla y manejarla. 3) Capturar la excepción y asociarla a una de las excepciones declaradas en el método. Excepciones Java try { “Sentencias con mensajes que pueden provocar excepciones” } catch (unaExcepcion e) {“codigo manejo excepción” } catch (OtraExcepcion e) {“codigo manejo excepción” } finally {...} // se ejecuta se lance o no una excepción Excepciones en Java ¡Una excepción es un objeto! try{ //sentencias }catch (TipoExcepcion1 e){ //manejar excepción }catch (TipoExcepcion2 e){ //manejar excepción } ... Ej: cerrar ficheros finally{ //sentencias que se ejecutan SIEMPRE //salte o no una excepción } Ejemplos public static int factorial (int n) throws NonPositiveException { if (n<=0) throw new NonPositiveException (“Num.factorial”); … } try { Num.factorial(y); } catch (NonPositiveException e) { … } Ejemplos public static int search (int [] a, int x) throws NullPointerException NoEncontradoException {…} try { …; try { x = Arrays.search(v,7);} catch (NullPointerException e) { throw new NoEncontradoException(); } } catch (NoEncontradoException e) {..} ¿Debo declarar NullPointerException en la signatura? ¿Es acertado considerar la situación de elemento no encontrado como una excepción? Captura de excepciones no comprobadas try { x = y [n]; i = Arrays.search(z, x);} catch (IndexOutOfBoundsException e) { “manejar la excepción en el caso del acceso y[n]” } No se sabe la procedencia exacta de la excepción no comprobada IndexOutOfBoundsException Restringir el ámbito de la sentencia try Ejemplos public class Arrays { public static int min (int [] a) throws NullPointerException, EmptyException { // EFECTO: Si a es null lanza NullPointerException, si no si a // está vacío lanza EmptyException, si no retorna el valor mínimo // del array a int m; try { m = a[0]; } catch (IndexOutOfBoundsException e) { throw new EmptyException(“Arrays.min”); } for (int i = 1; i < a.length; i++) if (a[i] < m) m = a[i]; return m; } Ejemplos public class Arrays { public static boolean sorted (int [] a) throws NullPointerException, EmptyException { // EFECTO: Si a es null lanza NullPointerException, si no retorna // true si el array está ordenado en orden ascendente si no false int prev; try { prev = a[0]; } catch (IndexOutOfBoundsException e) { return true; } for (int i = 1; i < a.length; i++) if (prev <= a[i]) prev = a[i]; else return false return true; }