Programación Java Curso 2006 - 1 C Excepciones Prof.. María Feldgen Ing. Osvaldo Clúa FIUBA Introducción: Excepciones. Son objetos que se crean para dar cuenta de algún evento que requiere tratamiento urgente. Interrumpen la ejecución del bloque. La siguiente clase se usa para operar con complejos con independencia de su representación (polar o cartesiana). No se muestran todos los métodos ya su construcción que forma parte de la guía de problemas. 1. /** Complejo 2. Maneja los complejos en forma transparente a su representación */ 3. public class Complejo{ 4. protected boolean polar=false; protected double real=0.0; 5. protected double imag=0.0; protected double rho=0.0; 6. protected double theta=0.0; 7. static final int POLAR=1; // constantes para su uso 8. static final int RECTA=2; // en los constructores 9. 10. Complejo (double uno,double dos,final int como) throws NoNormalizadoException{ 11. if (como ==RECTA) compRecta (uno,dos); 12. else compPolar (uno,dos); } 13. public void compRecta(double r,double i){ 14. polar=false; real=r; imag=i;} 15. public void compPolar(double r, double t)throws NoNormalizadoException{ 16. if (Math.abs(t) > 2*Math.PI) {throw new NoNormalizadoException(r,t);} 17. polar=true; rho=r;theta=t;} 18. // si se lanza la excepcion, la linea anterior no se hace nunca 19. 20. protected void toPolar(){...} 21. protected void toRect(){...} 22. private double grad(){...} 23. public String toString(){....} 24. public String enPolar(){...} 25. } En la clase anterior, el método compPolar( ... ) lanza una excepción llamada NoNormalizadoExcepción si su ángulo no está entre -2*PI y 2*PI. Esta excepción es un objeto cuyo constructor lleva dos parámetros que se usan para guardar los valores "ofensivos". La definición es: 1. -1- Java 2006 Guía 2 Prof.: Lic. Ing. Osvaldo Clúa Prof. C.C. Maria Feldgen FIUBA/EGRIET. 2. /** NoNormalizadoException Excepcion que se lanza al tratar de 3. crear un complejo polar con theta > 2*pi */ 4. class NoNormalizadoException extends Exception { 5. double rho ; // rho del complejo transgresor 6. double theta; // angulo del complejo agresor 7. NoNormalizadoException(double r,double t){ 8. rho=r;theta=t; } // guardo los valores ofensivos 9. public double getRho(){return rho;} 10. public double getTheta(){return theta;} 11.} Como la excepción no es tratada en el constructor de Complejo, este debe advertir que su ejecución puede lanzar la excepción. En una clase de prueba se ve como se trata la excepción 1. 2./** PruComp 3. prueba la clase complejo */ 4.class PruComp{ 5. public static void main(String args[]){ 6. try { 7. Complejo c1=new Complejo(4,4,Complejo.RECTA); 8. // esta va a funcionar bien 9. System.out.println("c1="+c1+" en polar es " +c1.enPolar()); 10. Complejo c2=new Complejo(5,4.5*Math.PI,Complejo.POLAR); 11. // esta no 12. System.out.println("c2="+c2+" en polar es " +c2.enPolar()); 13. } 14. catch ( NoNormalizadoException e ) { 15. System.out.println("Error en el angulo al intentar crear un complejo con rho ="+e.getRho()+" y angulo ="+e.getTheta()); } 16. finally { 17. System.out.println("Este bloque se ejecuta siempre");} 18. } 19.} El tratamiento se hace en un bloque try{...} catch(...){...} el bloque finally{...} es optativo. Problemas: 1. Programar una clase racional capaz de contener numerador y denominador enteros de un racional. Debe implementar constructor con valores, miembros de acceso y recuperación y una operación simplificar que reduce la fracción a números primos entre sí. Se implementará una excepción para impedir la creación de racionales con denominador cero. Los métodos internos y los miembros de datos deben ser protegidos y se debe implementar toString(). Programar pruebas para cada función implementada. Programar una clase instante que permita guardar las horas, minutos y segundos como enteros. Debe implementar constructor con valores, miembros de acceso y recuperación y una operación normalizar que reduce el valor a su forma normal (60 minutos = 1 hora, etc.). Además deberá implementar funciones de comparación por menor, igual o mayor. Los métodos internos y los miembros de datos deben ser protegidos y se debe implementar toString(). Programar pruebas para cada función implementada. Herencia. Supongamos una clase como la pedida en uno de los ejercicios de la guía para almacenar Racionales 1. /** Racional: Creacion y manejo de racionales, simplificacion */ -2- Java 2006 Guía 2 Prof.: Lic. Ing. Osvaldo Clúa Prof. C.C. Maria Feldgen FIUBA/EGRIET. 2. class Racional{ 3. private int num=0; 4. private int den=0; 5. Racional(int n,int d) throws CeroDenException 6. {if (d ==0) throw new CeroDenException(); 7. num=n; den=d;} 8. int getNum() {return num;} 9. int getDen() {return den;} 10. void setVal(int n, int d) {num=n; den=d;} 11. private int mcd(){ 12. if (num==0) return den; 13. else try{ return new Racional(den%num,num).mcd();} 14. catch (CeroDenException e ) {return 1;} 15. } 16. void simplificar() { 17. int mcd=mcd(); 18. num=num/mcd; den=den/mcd;} 19. public String toString(){return num+"/"+den;} 20.} Si se extiende esta clase, como por ejemplo: /** RacOrd: Un racional con igual, mayor y menor */ 1. class RacOrd extends Racional{ 2. RacOrd(int n, int d) throws CeroDenException { 3. super(n,d);} 4. boolean esIgual(RacOrd r){ return 5. r.getNum()==getNum() && r.getDen() == getDen();} 6. boolean esMayor(RacOrd r) { return 7. (double) getNum() / (double) getDen() >(double) r.getNum() /(double)r.getDen();} 8. boolean esMenor(RacOrd r) {return 9. (double) getNum() / (double) getDen() <(double) r.getNum() /(double)r.getDen();} 10.} La clase RacOrd extiende la clase racional. Esto significa que: Tiene acceso a todos sus campos public (como cualquier otra clase) y a los protected. Cualquier método de la clase Raciona puede ser usado con un objeto del tipo RacOrd. Un RacOrd tiene un objeto Racional como base. Por lo tanto es válido usar getNum() getDen() y Simplificar(). con un objeto RacOrd. No se puede, sin embargo, acceder a mcd() ya que es un método privado de la clase Racional. Y si quiero tener acceso a los campos num y den, lo debo hacer por medio de getNum() y getDen() ya que se trata de campos private. Al extender la clase, podría haber agregado nuevos campos, que estarían presentes en un objeto RacOrd pero no en uno Racional. El constructor: RacOrd(int n, int d) throws CeroDenException { super(n,d);} -3- Java 2006 Guía 2 Prof.: Lic. Ing. Osvaldo Clúa Prof. C.C. Maria Feldgen FIUBA/EGRIET. debe llamar al constructor de su clase base. De la misma forma que el objeto actual está siempre accesible desde el identificador this, la clase antecesora está disponible por el identificador super. El llamado super(n,d) es equivalente a Racional(n,d) y permite construir el objeto base Racional antes de construir el objeto RacOrd. Debe ser la primer sentencia en el constructor (el compilador lo obliga), de manera de tener el objeto base listo antes de ser usado. En cualquier lugar que se pueda usar un Racional, puede usarse un RacOrd. La inversa no es cierta. En la prueba: 1. /** PruRac: Prueba de los racionales */ 2. import java.io.*; 3. class PruRac1{ 4. public static void main(String arg[]) throws CeroDenException , IOException{ 5. BufferedReader in =new BufferedReader (new InputStreamReader (System.in)); 6. System.out.println(" Ingrese Numerador / Denominador"); 7. String st=new String(in.readLine()); 8. int barra=st.indexOf('/'); 9. int nu=new Integer(st.substring(0,barra)).intValue(); 10. int de=new Integer(st.substring(barra+1)).intValue(); 11. RacOrd a=new RacOrd(nu,de); 12. System.out.println ("El Racional a "+a); 13. a.simplificar(); 14. System.out.println ("Simplificado "+a); 15. System.out.println(" Ingrese Numerador / Denominador"); 16. st=in.readLine(); 17. barra=st.indexOf('/'); 18. nu=new Integer(st.substring(0,barra)).intValue(); 19. de=new Integer(st.substring(barra+1)).intValue(); 20. RacOrd b=new RacOrd(nu,de); 21. System.out.println ("El Racional b "+b); 22. b.simplificar(); 23. System.out.println ("Simplificado "+b); 24. System.out.println(" b mayor que a "+b.esMayor(a)); 25. System.out.println(" a mayor que b "+a.esMayor(b)); 26. System.out.println(" b y a son iguales "+b.esIgual(a)); 27. } 28.} ... se puede ver una llamada a simplificar() de un RacOrd. En esta prueba se incluye una entrada de Números Racionales que puede servir como ejemplo para desarrollar la I/O de los diversos tipos. Se sugiere convertirla en método e incorporarla a la clase base. Si un método se redefine (reprograma) en una clase derivada, se dice que se especializa al método o que se hace un override del método. AL buscar un método se comienza por la clase a la que pertenece, luego por su antecesora y así sucesivamente hasta llegar al la "madre de todas las clases Java" que es Object Cuando se programa toString() en realidad se hace un override de Object.toString(). Como lectura adicional: la documentación de las API (por ejemplo la clase String) y el texto Java Language Specification, que se obtiene de http://www.java.sun.com. -4- Java 2006 Guía 2 Prof.: Lic. Ing. Osvaldo Clúa Prof. C.C. Maria Feldgen FIUBA/EGRIET. La relación de herencia se conoce como relación isA y no debe confundirse con la relación de contenido, agregación o hasA. El contenido en Java se programa haciendo una clase campo (miembro) de otra clase (Por ejemplo, una Clase Persona tiene un objeto de la clase String en su interior). Si bien los dibujos normales pueden dar lugar a confusión, la diferencia resulta obvia si se lo piensa en los siguientes términos. ¿Todo B es un A? (¿Todo RacOrd es un Racional?) se trata de herencia isA. ¿B contiene un objeto de A (un método de A puede aplicarse a todo B o solo a una parte)? se trata de agregación hasA Simplificar() se puede aplicar a cualquier RacOrd, en tanto charAt() solo se puede aplicar a un campo String de Persona. 4) Extender la clase racional con funciones booleanas de comparación por menor, igual y mayor. Programar pruebas para cada función implementada. 5) Extender la clase instante para permitir la función avanzar( segundos) que avanza el instante en tantos segundos. Programar una excepción que se lance al intentar construir un instante extendido no normalizado. Además deberá proveer la función duración que indicará en segundos la diferencia entre dos instantes. Programar pruebas para cada función implementada y se usará la excepción para normalizar el instante extendido. 6) Extender la clase complejo con funciones de suma, resta, multiplicación y división.. Programar pruebas para cada función implementada. -5-