Mostrando entradas con la etiqueta Exception. Mostrar todas las entradas
Mostrando entradas con la etiqueta Exception. Mostrar todas las entradas

domingo, 6 de noviembre de 2011

Ejercicio "Efemérides" (base de datos)

Crear una aplicación que permita gestionar una base de datos de efemérides. Todas las operaciones se realizarán mediante consola, ya que el tema de formularios lo hemos empezado a ver después del de acceso a bases de datos.

Para empezar creamos en Access la base de datos "efemerides", que contendrá una única entidad: "efemeride", con los siguientes atributos:
  • id. De tipo entero.
  • texto. De tipo texto.
  • fecha. De tipo fecha.
Una vez creada la base de datos, implementamos el puente JDBC-ODBC y empezamos a trabajar.

Dentro de nuestro proyecto, crearemos la clase "BaseDatos" y el fichero de configuración, que como vimos en la entrada anterior nos facilitan todas las gestiones que realicemos con respecto al acceso a bases de datos.

Además, para que todo sea más realista y más sencillo de entender para el programador, crearemos la clase "Efemeride", que tendrá los atributos propios de una efeméride y, como métodos, los correspondientes "getters" y "setters".

CLASE EFEMERIDE

public class Efemeride {
 private Integer id;
 private String texto;
 private Date fecha;

 public Integer getId() {
  return id;
 }

 public void setId(Integer id) {
  this.id = id;
 }

 public String getTexto() {
  return texto;
 }

 public void setTexto(String texto) {
  this.texto = texto;
 }

 public Date getFecha() {
  return fecha;
 }

 public void setFecha(Date fecha) {
  this.fecha = fecha;
 }
}

TRUCO: una vez que has especificado todos los atributos de una clase, en Eclipse es muy sencillo generar los métodos getAtributo() y setAtributo(Dato dato). Sólo tienes que hacer clic con el botón derecho y en "Source" elegir "Generate Getters and Setters". En el cuadro de diálogo que se abre eliges los atributos de los que quieres generar estos métodos, haces clic en "OK" y ¡listo!

Para controlar las excepciones de nuestra aplicación, crearemos nuestra propia excepción. En nuestro caso esta clase fue facilitada por el profesor, así como una interfaz ("IEfemerides") que debe implementar la clase "Efemerides". Esta clase es la encargada de realizar todas las gestiones con la base de datos (insertar datos, actualizar, recuperar, etc.).

CLASE EFEMERIDEEXCEPTION

public class EfemerideException extends Exception {
 private static final long serialVersionUID = 1L;

 public EfemerideException(String mensaje) {
  super(mensaje);
 }
 
}

CLASE EFEMERIDES

public class Efemerides implements IEfemerides {

 @Override
 public void insertar(Efemeride efemeride) throws EfemerideException {
  try {
   Connection conexion = BaseDatos.getConnection();
   String sql = "insert into efemerides (texto, fecha) values (?, ?)";
   PreparedStatement insertar = conexion.prepareStatement(sql);

   insertar.setString(1, efemeride.getTexto());
   insertar.setDate(2, DateUtils.convertir(efemeride.getFecha()));

   insertar.executeUpdate();
   insertar.close();

  } catch (SQLException e) {
   e.printStackTrace();
   throw new EfemerideException("No se ha podido insertar la efeméride.");
  }
 }

 @Override
 public void eliminar(Integer id) throws EfemerideException {
  try {
   int eliminado;
   Connection conexion = BaseDatos.getConnection();
   String sql = "delete from efemerides where id=?";
   PreparedStatement eliminar = conexion.prepareStatement(sql);

   eliminar.setInt(1, id);

   eliminado = eliminar.executeUpdate();
   if (eliminado == 0) {
    throw new EfemerideException("La efeméride no existe.");
   }
   eliminar.close();

  } catch (SQLException e) {
   e.printStackTrace();
   throw new EfemerideException("No se ha podido eliminar la efeméride.");
  }
 }

 @Override
 public void actualizar(Efemeride efemeride) throws EfemerideException {
  try {
   int actualizado;
   Connection conexion = BaseDatos.getConnection();
   String sql = "update efemerides set texto=?, fecha=? where id=?";
   PreparedStatement actualizar = conexion.prepareStatement(sql);

   actualizar.setString(1, efemeride.getTexto());
   actualizar.setDate(2, DateUtils.convertir(efemeride.getFecha()));
   actualizar.setInt(3, efemeride.getId());

   actualizado=actualizar.executeUpdate();
   if (actualizado == 0) {
    throw new EfemerideException("La efeméride no existe, por lo que no se ha podido actualizar.");
   }
   actualizar.close();

  } catch (SQLException e) {
   e.printStackTrace();
   throw new EfemerideException("No se ha podido actualizar la efeméride.");
  }

 }

 @Override
 public Efemeride recuperar(Integer id) throws EfemerideException {
  Efemeride efemeride = new Efemeride();
  try {
   Connection conexion = BaseDatos.getConnection();
   String sql = "select * from efemerides where id=?";
   PreparedStatement recuperar = conexion.prepareStatement(sql);

   recuperar.setInt(1, id);

   ResultSet resultado = recuperar.executeQuery();
   if (!resultado.next()) {
    throw new EfemerideException("La efeméride no se ha recuperado porque no existe.");
   } else {
    efemeride.setId(id);
    efemeride.setTexto(resultado.getString("texto"));
    efemeride.setFecha(resultado.getDate("fecha"));
   }
  } catch (SQLException e) {
   e.printStackTrace();
   throw new EfemerideException("No se ha podido recuperar la efeméride.");
  }
  return efemeride;
 }

 @Override
 public List<Efemeride> hoy() throws EfemerideException {
  Date hoy = new Date();

  return recuperarPorFecha(hoy);
 }

 @Override
 public List<Efemeride> recuperarTodas() throws EfemerideException {
  List<Efemeride> listado = new ArrayList<Efemeride>();
  try {
   Connection conexion = BaseDatos.getConnection();
   Statement recuperar = conexion.createStatement();

   ResultSet resultado;
   resultado = recuperar.executeQuery("select * from efemerides");

   while (resultado.next()) {
    Efemeride efemeride = new Efemeride();
    efemeride.setId(resultado.getInt("id"));
    efemeride.setTexto(resultado.getString("texto"));
    efemeride.setFecha(resultado.getDate("fecha"));
    listado.add(efemeride);
   }
  } catch (SQLException e) {
   e.printStackTrace();
   throw new EfemerideException("No se han podido recuperar las efemérides.");
  }
  return listado;
 }

 @Override
 public List<Efemeride> recuperarPorFecha(Date fecha)
   throws EfemerideException {
  List<Efemeride> listado = new ArrayList<Efemeride>();
  try {
   Connection conexion = BaseDatos.getConnection();
   String sql = "select * from efemerides where day(fecha)=? and month(fecha)=?";
   PreparedStatement recuperar = conexion.prepareStatement(sql);

   recuperar.setInt(1, DateUtils.dia(fecha));
   recuperar.setInt(2, DateUtils.mes(fecha));

   ResultSet resultado = recuperar.executeQuery();
   while (resultado.next()) {
    Efemeride efemeride = new Efemeride();
    efemeride.setId(resultado.getInt("id"));
    efemeride.setTexto(resultado.getString("texto"));
    efemeride.setFecha(resultado.getDate("fecha"));
    listado.add(efemeride);
   }
  } catch (SQLException e) {
   e.printStackTrace();
   throw new EfemerideException("No se han podido recuperar las efemérides.");
  }
  return listado;
 }

}

Finalmente, la aplicación con la que interactuará el usuario se creó utilizando varias clases proporcionadas por el profesor, que permitían crear menús y recoger los datos introducidos por el usuario.

CLASE MENUEFEMERIFE

public class MenuEfemeride {

 private static Efemerides efemerides = new Efemerides();
 
 public static void main(String[] args) {

  Menu principal = new Menu("Menú principal. Efemérides");
  Menu consultar = new Menu("Consultar");
  
  Accion insertarEfemeride = new Accion("Insertar efeméride") {
   public void accion() { onInsertarEfemeride(); }
  };
  Accion eliminarEfemeride = new Accion("Eliminar efeméride") {
   public void accion() { onEliminarEfemeride(); }
  };
  Accion actualizarEfemeride = new Accion("Actualizar efeméride") {
   public void accion() { onActualizarEfemeride(); }
  };
  Accion buscarPorId = new Accion("Buscar efeméride por identificador") {
   public void accion() { onBuscarPorId(); }
  };
  Accion buscarPorFecha = new Accion("Buscar efeméride por fecha") {
   public void accion() { onBuscarPorFecha(); }
  };
  Accion efemeridesHoy = new Accion("Efemérides de hoy") {
   public void accion() { onEfemeridesHoy(); }
  };
  Accion todas = new Accion("Todas las efemérides") {
   public void accion() { onTodas(); }
  };
  
  consultar.agregar(buscarPorId);
  consultar.agregar(buscarPorFecha);
  consultar.agregar(efemeridesHoy);
  consultar.agregar(todas);
  consultar.agregar(new OpcionSalir("Volver"));
  
  principal.agregar(insertarEfemeride);
  principal.agregar(eliminarEfemeride);
  principal.agregar(actualizarEfemeride);
  principal.agregar(consultar);
  principal.agregar(new OpcionSalir("Salir"));
  
  principal.ejecutar();
  
  BaseDatos.desconectar();

 }

 protected static void onInsertarEfemeride() {

  Efemeride efemeride = new Efemeride();
  
  String texto = Entrada.leerCadena("Introduzca el texto de la efeméride");
  String fechaTexto = Entrada.leerCadena("Introduzca la fecha (dd/mm/aaaa)");
  String[] partes = fechaTexto.split("/");
  
  GregorianCalendar fecha = new GregorianCalendar(Integer.parseInt(partes[2]), (Integer.parseInt(partes[1])-1), Integer.parseInt(partes[0]));

  efemeride.setTexto(texto);
  efemeride.setFecha(fecha.getTime());
  
  try {
   efemerides.insertar(efemeride);
   System.out.println("**EFEMÉRIDE INSERTADA CON ÉXITO**");
   Entrada.pausa();
  } catch (EfemerideException e) {
   System.err.println(e.getMessage());
   Entrada.pausa();
  }
  
 }
 
 protected static void onEliminarEfemeride() {

  Integer id = Entrada.leerEntero("Introduzca el identificador de la efeméride a eliminar");
  
  try {
   efemerides.eliminar(id);
   System.out.println("**EFEMÉRIDE ELIMINADA**");
   Entrada.pausa();
  } catch (EfemerideException e) {
   System.err.println(e.getMessage());
   Entrada.pausa();
  }
  
 }

 protected static void onActualizarEfemeride() {

  Efemeride efemeride = new Efemeride();
  Integer id = Entrada.leerEntero("Introduzca el identificador de la efeméride a actualizar");
  try {
   Efemeride recuperada = efemerides.recuperar(id);
   System.out.println("Datos de la efeméride a actualizar:");
   System.out.println("Id: "+id+" - Texto: "+recuperada.getTexto()+" - Fecha: "+DateUtils.formatear(recuperada.getFecha()));
   
   String texto = Entrada.leerCadena("Introduzca el nuevo texto de la efeméride");
   String fechaTexto = Entrada.leerCadena("Introduzca la nueva fecha (dd/mm/aaaa)");
   
   String[] partes = fechaTexto.split("/");
   GregorianCalendar fecha = new GregorianCalendar(Integer.parseInt(partes[2]), (Integer.parseInt(partes[1])-1), Integer.parseInt(partes[0]));

   efemeride.setId(id);
   efemeride.setTexto(texto);
   efemeride.setFecha(fecha.getTime());
   
   efemerides.actualizar(efemeride);
   System.out.println("**EFEMÉRIDE ACTUALIZADA CON ÉXITO**");
   Entrada.pausa();
  } catch (EfemerideException e) {
   System.err.println(e.getMessage());
   Entrada.pausa();
  }
 }
 
 protected static void onBuscarPorId() {

  Integer id = Entrada.leerEntero("Introduzca el identificador de la efeméride a buscar");
  try {
   Efemeride efemeride = efemerides.recuperar(id);
   System.out.println("DATOS DE LA EFEMÉRIDE:");
   System.out.println("Id: "+id+" - Texto: "+efemeride.getTexto()+" - Fecha: "+DateUtils.formatear(efemeride.getFecha()));
   Entrada.pausa();
  } catch (EfemerideException e) {
   System.err.println(e.getMessage());
   Entrada.pausa();
  }
 }
 
 protected static void onBuscarPorFecha() {

  String fechaTexto = Entrada.leerCadena("Introduzca la fecha (dd/mm) de las efemérides a buscar");
  String[] partes = fechaTexto.split("/");
  
  GregorianCalendar fecha = new GregorianCalendar(1999, (Integer.parseInt(partes[1])-1), Integer.parseInt(partes[0]));
  
  try {
   List <Efemeride> listado = efemerides.recuperarPorFecha(fecha.getTime());
   if (listado.isEmpty()) {
    System.out.println("**NO HAY EFEMÉRIDES PARA EL DÍA ESPECIFICADO**");
   }
   else {
    System.out.println("LISTADO DE LAS EFEMÉRIDES:");
    for (Efemeride efemeride : listado) {
     System.out.println("Id: "+efemeride.getId()+" - Texto: "+efemeride.getTexto()+" - Fecha: "+DateUtils.formatear(efemeride.getFecha()));
    }
   }
   Entrada.pausa();
   
  } catch (EfemerideException e) {
   System.err.println(e.getMessage());
   Entrada.pausa();
  }
  
 }
 
 protected static void onEfemeridesHoy() {
  
  try {
   List <Efemeride> listado = efemerides.hoy();
   if (listado.isEmpty()) {
    System.out.println("**NO HAY EFEMÉRIDES PARA EL DÍA DE HOY**");
   }
   else {
    System.out.println("LISTADO DE LAS EFEMÉRIDES DE HOY:");
    for (Efemeride efemeride : listado) {
     System.out.println("Id: "+efemeride.getId()+" - Texto: "+DateUtils.formatear(efemeride.getFecha()));
    }
   }
   Entrada.pausa();
  } catch (EfemerideException e) {
   System.err.println(e.getMessage());
   Entrada.pausa();
  }
 }
 
 protected static void onTodas() {
  try {
   List <Efemeride> listado = efemerides.recuperarTodas();
   if (listado.isEmpty()) {
    System.out.println("**NO HAY EFEMÉRIDES ALMACENADAS**");
   }
   else {
    System.out.println("LISTADO DE TODAS LAS EFEMÉRIDES:");
    for (Efemeride efemeride : listado) {
     System.out.println("Id: "+efemeride.getId()+" - Texto: "+efemeride.getTexto()+" - Fecha: "+DateUtils.formatear(efemeride.getFecha()));
    }
   }
   Entrada.pausa();
  } catch (EfemerideException e) {
   System.err.println(e.getMessage());
   Entrada.pausa();
  }  
 }

}

También se creó una clase con utilidades para trabajar con las fechas, debido a que nos veíamos en la obligación de utilizar por una parte la clase java.util.Date y por otra java.sql.Date. Esta clase, como la clase "BaseDatos", se puede reutilizar cada vez que tengamos que trabajar con fechas en el acceso a bases de datos.

CLASE DATEUTILS

public class DateUtils {
 
 public static java.util.Date crearFecha(int dia, int mes, int anyo) {
  GregorianCalendar calendario = new GregorianCalendar(anyo, mes-1, dia);
  return calendario.getTime();
 }
 
 public static java.sql.Date convertir(java.util.Date fecha) {
  return new java.sql.Date(fecha.getTime());
 }
 
 public static int dia(java.util.Date fecha) {
  GregorianCalendar calendario = new GregorianCalendar();
  calendario.setTime(fecha);
  
  return calendario.get(Calendar.DAY_OF_MONTH);
 }
 
 public static int mes(java.util.Date fecha) {
  GregorianCalendar calendario = new GregorianCalendar();
  calendario.setTime(fecha);
  
  return calendario.get(Calendar.MONTH)+1;
 }
 
 public static int anyo(java.util.Date fecha) {
  GregorianCalendar calendario = new GregorianCalendar();
  calendario.setTime(fecha);
  
  return calendario.get(Calendar.YEAR);
 }
 
 public static String formatear(java.util.Date fecha) {
  SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
  return formatter.format(fecha);
 }

}

viernes, 9 de septiembre de 2011

Ejercicio "Figuras geométricas"

Este ejercicio lo realizamos a lo largo de varias semanas, añadiendo funciones, creando clases nuevas y realizando algunos ejercicios con las figuras que se añadirán en entradas posteriores.

Dada la clase abstracta* "Figura", añadirle varias funciones de desplazamiento, una función que permita consultar su posición y dos funciones que permitan modificar directamente las coordenadas.

public abstract class Figura implements Serializable {
    protected  Point posicion;
    public Figura(int a, int b) {
    posicion= new Point(a,b);}
    public abstract float area();
    public abstract float perimetro();
    public abstract int alto();
    public abstract int ancho();
    public abstract void dibujar(Graphics g);
    public abstract void guardar(OutputStream out) throws IOException;
    public abstract void cargar(InputStream in) throws IOException;
    public void arr(int incremento){
        this.posicion.y -= incremento;
    }
    public void abj(int incremento){
        this.posicion.y += incremento;
    }
    public void izq(int incremento){
        this.posicion.x -= incremento;
    }
    public void der(int incremento){
        this.posicion.x += incremento;
    }
    public Point posicion(){
        Point aux = new Point(posicion);
        return aux;
    }
    public void set_y(int pos_y){
        this.posicion.y = pos_y;
    }
    public void set_x(int pos_x){
        this.posicion.x = pos_x;
    }
}

Crear la clase (excepción) "FiguraFormatException", que hereda de "IllegalArgumentException" y se lanzará si en la función Cargar, se lee del flujo una figura que no es la indicada.

public class FiguraFormatException extends IllegalArgumentException{
    public FiguraFormatException() {
    }
    public FiguraFormatException(String string) {
        super(string);
    }
}

Dadas las clases "Triangulo", "Elipse", "Circulo", "Rectangulo" y "Cuadrado", que heredan de la clase abstracta "Figura", añadir un constructor que reciba un InputStream, que tendrá los datos adecuados para inicializar la figura. Además, se sobreescribirán las funciones abstractas de la clase "Figura".

CLASE Triangulo

public class Triangulo extends Figura {
    protected int lado1, lado2, lado3;
    private int lx, altura;
    public Triangulo(int a, int b, int c, int d, int e) {
        super(a, b);
        int elMayor = (c > d & c > e) ? c : ((d > e) ? d : e);
        if (elMayor >= (c + d + e - elMayor)) {
            throw new IllegalArgumentException("Los lados del triangulo son imposibles");
        }
        lado1 = c;
        lado2 = d;
        lado3 = e;
        lx = (lado2 * lado2 - lado3 * lado3 - lado1 * lado1) / (2 * lado1);
        altura = (int) Math.sqrt(lado3 * lado3 - lx * lx);
    }
    public Triangulo(InputStream in) throws IOException {
        super(0, 0);
        cargar(in);
    }
    public void guardar(OutputStream out) throws IOException {
        DataOutputStream escribir = new DataOutputStream(out);
        escribir.writeUTF("figuras.Triangulo");
        escribir.writeInt(posicion.x);
        escribir.writeInt(posicion.y);
        escribir.writeInt(lado1);
        escribir.writeInt(lado2);
        escribir.writeInt(lado3);
        escribir.flush();
    }
    public void cargar(InputStream in) throws IOException {
        DataInputStream leer = new DataInputStream(in);
        String figura;
        figura = leer.readUTF();
        if (!figura.equals("figuras.Triangulo")) {
            throw new FiguraFormatException();
        }
        posicion.x = leer.readInt();
        posicion.y = leer.readInt();
        lado1 = leer.readInt();
        lado2 = leer.readInt();
        lado3 = leer.readInt();
        lx = (lado2 * lado2 - lado3 * lado3 - lado1 * lado1) / (2 * lado1);
        altura = (int) Math.sqrt(lado3 * lado3 - lx * lx);
    }
    public float area() {
        return (lado1 * altura) / 2;
    }
    public float perimetro() {
        return lado1 + lado2 + lado3;
    }
    public int alto() {
        return altura;
    }
    public int ancho() {
        return lado1;
    }
    public void dibujar(Graphics g) {
        Color cActual = g.getColor();
        int[] xPuntos = {posicion.x,
            posicion.x + lado1,
            posicion.x + lado1 + lx};
        int[] yPuntos = {posicion.y,
            posicion.y,
            posicion.y + altura};
        g.fillPolygon(xPuntos, yPuntos, 3);
        g.setColor(Color.white);
        g.drawPolygon(xPuntos, yPuntos, 3);
        g.setColor(cActual);
    }
}

CLASE Elipse

public class Elipse extends Figura {
    public final static float PI = 3.1415F;
    protected int dMenor, dMayor;
    public Elipse(int a, int b, int c, int d) {
        super(a, b);
        dMenor = c;
        dMayor = d;
    }
    public Elipse(InputStream in) throws IOException {
        super(0, 0);
        this.cargar(in);
    }
    public void guardar(OutputStream out) throws IOException {
        DataOutputStream escribir = new DataOutputStream(out);
        escribir.writeUTF("figuras.Elipse");
        escribir.writeInt(posicion.x);
        escribir.writeInt(posicion.y);
        escribir.writeInt(dMenor);
        escribir.writeInt(dMayor);
        escribir.flush();
    }
    public void cargar(InputStream in) throws IOException {
        DataInputStream leer = new DataInputStream(in);
        if (!leer.readUTF().equals("figuras.Elipse")) {
            throw new FiguraFormatException();
        }
        posicion.x = leer.readInt();
        posicion.y = leer.readInt();
        dMenor = leer.readInt();
        dMayor = leer.readInt();
    }
    public float area() {
        return PI * dMenor * dMayor;
    }
    public float perimetro() {
        return PI * (dMenor + dMayor);
    }
    public int alto() {
        return dMayor;
    }
    public int ancho() {
        return dMenor;
    }
    public void dibujar(Graphics g) {
        Color cActual = g.getColor();
        g.fillOval(posicion.x, posicion.y, dMenor, dMayor);
        g.setColor(Color.white);
        g.drawOval(posicion.x, posicion.y, dMenor, dMayor);
        g.setColor(cActual);
    }
}

CLASE Circulo

public class Circulo extends Elipse {
    public Circulo(int a, int b, int d) {
        super(a, b, d, d);
    }
    public Circulo(InputStream is) throws IOException {
        super(0, 0, 0, 0);
        //Si se produce una IOException, se borrarán los datos del objeto Circulo
        cargar(is);
    }
    @Override
    public void guardar(OutputStream os) throws IOException {
        DataOutputStream dos = new DataOutputStream(os);
        dos.writeUTF("figuras.Circulo");
        dos.writeInt(posicion.x);
        dos.writeInt(posicion.y);
        dos.writeInt(dMayor);
        dos.flush();
    }
    @Override
    public void cargar(InputStream is) throws IOException {
        DataInputStream dis = new DataInputStream(is);

        if (!dis.readUTF().equals("figuras.Circulo")) {
            throw new FiguraFormatException();
        }
        posicion = new Point(dis.readInt(), dis.readInt());
        dMayor = dis.readInt();
        dMenor = dMayor;
    }
}

CLASE Rectangulo

public class Rectangulo extends Figura {
    protected int lado1, lado2;
    public Rectangulo(int a,int b,int c,int d) {
        super(a,b);
        lado1=c;
        lado2=d; }
    public Rectangulo(InputStream in) throws IOException {
        super(0,0);
        this.cargar(in);
    }
    public float area() {
        return lado1*lado2;
    }
    public float perimetro() {
        return lado1*2+lado2*2;
    }
    public int alto() {
        return lado2;
    }
    public int ancho() {
        return lado1;
    }
    public void dibujar(Graphics g) {
        Color cActual=g.getColor();
        g.fillRect(posicion.x,posicion.y,lado1,lado2);
        g.setColor(Color.white);
        g.drawRect(posicion.x,posicion.y,lado1,lado2);
        g.setColor(cActual);
    }
    public void guardar (OutputStream out) throws IOException{
        DataOutputStream dos = new DataOutputStream(out);
        dos.writeUTF("figuras.Rectangulo");
        dos.writeInt((int) super.posicion().getX());
        dos.writeInt((int) super.posicion().getY());
        dos.writeInt(lado1);
        dos.writeInt(lado2);
        dos.flush();
    }
    public void cargar (InputStream in) throws IOException{
        DataInputStream dis = new DataInputStream(in);
        if(!dis.readUTF().equals("figuras.Rectangulo")) {
            throw new FiguraFormatException("La figura no es un rectángulo.");
        }
        super.set_x(dis.readInt());
        super.set_y(dis.readInt());
        lado1=dis.readInt();
        lado2=dis.readInt();
    }
}

CLASE Cuadrado

public class Cuadrado extends Rectangulo {
    public Cuadrado(int a, int b, int c) {
        super(a, b, c, c);
    }
    public Cuadrado(InputStream in) throws IOException {
        super(0, 0, 0, 0);
        cargar(in);
    }
    @Override
    public void guardar(OutputStream out) throws IOException {
        DataOutputStream escribe = new DataOutputStream(out);
        escribe.writeUTF("figuras.Cuadrado");
        escribe.writeInt(posicion.x);
        escribe.writeInt(posicion.y);
        escribe.writeInt(this.alto());
        escribe.flush();
    }
    @Override
    public void cargar(InputStream in) throws IOException {
        DataInputStream lee = new DataInputStream(in);
        if (!lee.readUTF().equals("figuras.Cuadrado")) {
            throw new FiguraFormatException();
        }
        posicion.x = lee.readInt();
        posicion.y = lee.readInt();
        lado1 = lee.readInt();
        lado2 = lado1;
    }
}

Crear las clases "TEquilatero" que hereda de "Triangulo" y "Coche" que hereda de "Figura".

La clase "TEquilatero":
  • Es un triángulo con los tres lados iguales.

La clase "Coche":

  • Estará formada por dos círculos (ruedas) y un rectángulo.
  • Su posición la indicará la esquina superior izquierda.
  • Los círculos tendrán el mismo tamaño que la altura del rectángulo.
    • Si la suma de los dos diámetros es mayor a la longitud del rectángulo, entonces el diámetro será la mitad de la longitud.
CLASE TEquilatero

public class TEquilatero extends Triangulo {
    public TEquilatero(int a, int b, int c) {
        super(a, b, c, c, c);
    }
    public TEquilatero(InputStream in) throws IOException {
        super(0, 0, 0, 0, 0);
        cargar(in);
    }
    @Override
    public void cargar(InputStream into) throws IOException {
        DataInputStream di = new DataInputStream(into);
        if (!di.readUTF().equals("figuras.TEquilatero")) {
            throw new FiguraFormatException();
        }
        posicion.x = di.readInt();
        posicion.y = di.readInt();
        lado1 = di.readInt();
    }
    @Override
    public void guardar(OutputStream o) throws IOException {
        DataOutputStream out = new DataOutputStream(o);
        out.writeUTF("figuras.TEquilatero");
        out.writeInt(posicion.x);
        out.writeInt(posicion.y);
        out.writeInt(lado1);
        out.flush();
    }
}

CLASE Coche

public class Coche extends Figura {
    private Rectangulo chasis;
    private Circulo rueda1, rueda2;
    public Coche(int a, int b, int alto, int ancho) {
        super(a, b);
        if (alto <= ancho) {
            chasis = new Rectangulo(a, b, ancho, alto / 2);
            rueda1 = new Circulo(a, b + chasis.alto(), alto / 2);
            rueda2 = new Circulo(a + ancho - alto / 2, b + chasis.alto(), alto / 2);
        } else {
            chasis = new Rectangulo(a, b, ancho, alto - (ancho / 2));
            rueda1 = new Circulo(a, b + chasis.alto(), ancho / 2);
            rueda2 = new Circulo(a + ancho / 2, b + chasis.alto(), ancho / 2);
        }
    }
    public Coche(InputStream in)throws IOException{
        super(0,0);
        this.cargar(in);
    }
    @Override
    public float area() {
        return chasis.area() + rueda1.area() + rueda2.area();
    }
    @Override
    public float perimetro() {
        return chasis.perimetro() + rueda1.perimetro() + rueda2.perimetro();
    }
    @Override
    public int alto() {
        return chasis.alto() + rueda1.alto();
    }
    @Override
    public int ancho() {
        return chasis.ancho();
    }
    @Override
    public void dibujar(Graphics g) {
        chasis.dibujar(g);
        rueda1.dibujar(g);
        rueda2.dibujar(g);
    }
    @Override
    public void arr(int incremento) {
        super.arr(incremento);
        chasis.arr(incremento);
        rueda1.arr(incremento);
        rueda2.arr(incremento);
    }
    @Override
    public void abj(int incremento) {
        super.abj(incremento);
        chasis.abj(incremento);
        rueda1.abj(incremento);
        rueda2.abj(incremento);
    }
    @Override
    public void izq(int incremento) {
        super.izq(incremento);
        chasis.izq(incremento);
        rueda1.izq(incremento);
        rueda2.izq(incremento);
    }
    @Override
    public void der(int incremento) {
        super.der(incremento);
        chasis.der(incremento);
        rueda1.der(incremento);
        rueda2.der(incremento);
    }
    @Override
    public void set_y(int pos_y) {
        super.set_y(pos_y);
        chasis.set_y(pos_y);
        rueda1.set_y(pos_y + chasis.alto());
        rueda2.set_y(pos_y + chasis.alto());
    }
    @Override
    public void set_x(int pos_x) {
        super.set_x(pos_x);
        chasis.set_x(pos_x);
        rueda1.set_x(pos_x);
        rueda2.set_x(pos_x + chasis.ancho() - rueda2.ancho());
    }
    public void guardar(OutputStream out) throws IOException {
        DataOutputStream escribe = new DataOutputStream(out);
        escribe.writeUTF("figuras.Coche");
        escribe.writeInt(posicion.x);
        escribe.writeInt(posicion.y);
        escribe.flush();
        rueda1.guardar(out);
        rueda2.guardar(out);
        chasis.guardar(out);

    }
    public void cargar(InputStream in) throws IOException {
        DataInputStream leer = new DataInputStream(in);
        String clase;
        if (!(clase=leer.readUTF()).equals("figuras.Coche")) {
            throw new FiguraFormatException("La figura no es un coche. Se ha leído: "+clase);
        }
        posicion.x = (leer.readInt());
        posicion.y = (leer.readInt());
        rueda1 = new Circulo(in);
        rueda2 = new Circulo(in);
        chasis = new Rectangulo(in);
    }
}

* Una clase será abstracta cuando no queremos que se puedan crear objetos de esa clase. Sus funciones pueden ser abstractas, en este caso, las clases que hereden de una abstracta pueden sobreescribir esas funciones o dejarla abstracta (la clase hija será también abstracta). Una clase abstracta también puede tener funciones no abstractas, es decir, que tengan código.

sábado, 27 de agosto de 2011

Ejercicio "Fracción" (modificación)

Modificar la clase Fraccion, de manera que implemente las interfaces Comparable y Reseteable, es decir, debe poner código a las funciones de esas interfaces. Como las interfaces se encuentran en otro paquete distinto a la clase Fraccion, se deben importar.
Además, se creará la excepción FraccionException, que se lanzará en el constructor de la clase Fraccion cuando el denominador sea 0.

EXCEPCIÓN: FraccionException

public class FraccionException extends ArithmeticException {
    public FraccionException(){
    }
    public FraccionException(String mensaje){
        super(mensaje);
    }
}

Las excepciones se programan normalmente con dos constructores:
  • Uno por defecto, que no recibe nada.
  • Otro que recibe un String, con el texto que queremos que se muestre si se lanza esa excepción.
Las excepciones pueden heredar de las existentes en Java, siempre que tenga sentido que así sea. Si queremos que la excepción no sea marcada, heredará de RuntimeException o de alguna de las que están dentro de ese conjunto.

CLASE: Fraccion

import interfaces.Comparable;
import interfaces.Reseteable;

public class Fraccion implements Comparable, Reseteable {
    private int numerador;
    private int denominador;
    public Fraccion(int num){
        this(num, 1);
    }
    public Fraccion(int num, int den){
        if (den == 0)
            throw new FraccionException();
        numerador = num;
        denominador = den;
    }
    public Fraccion inversa() {
        Fraccion aux;
        aux = new Fraccion(denominador, numerador);
        return aux;
    }
    public Fraccion producto(Fraccion f) {
        Fraccion resultado;
        int numRes, denRes;
        numRes = f.numerador * numerador;
        denRes = f.denominador * denominador;
        resultado = new Fraccion(numRes, denRes);
        return resultado;
    }
    @Override
    public String toString() {
        return numerador+"/"+denominador;
    }
    public Fraccion opuesta() {
        Fraccion aux;
        aux = new Fraccion(-numerador, denominador);

        return aux;
    }
    public static int mcd(int num1, int num2) {
        int aux;
        //Algoritmo de Euclides
        while (num2 != 0){
            aux = num1;
            num1 = num2;
            num2 = aux % num2;
        }
        return num1;
    }
    public static int mcm(int num1, int num2) {
        int mcm;
        int a=num1, b=num2;

        while (num1 != num2){
            if (num1>num2)
                num1 = num1-num2;
            else
                num2 = num2-num1;
        }
        mcm = a*b/num2;
        return mcm;
    }
    public Fraccion suma(Fraccion f2) {
        Fraccion resultado;
        int minimo, num;
        minimo = mcm(denominador, f2.denominador);
        num = (minimo/denominador)*numerador + (minimo/f2.denominador)*f2.numerador;
        resultado = new Fraccion(num, minimo);
        return resultado;
    }
    public boolean equals(Fraccion f2) {
        return numerador==f2.numerador & denominador==f2.denominador;
    }
    public Fraccion simplificar() {
        int divisor;
        divisor = mcd(numerador, denominador);
        numerador = numerador/divisor;
        denominador = denominador/divisor;
        return this;
    }
    public int comparadoCon(Object obj) throws ClassCastException {
        Fraccion f2 = (Fraccion) obj;
        double prim, segun;
        int res;
        prim = numerador/(double)denominador;
        segun = f2.numerador/(double)f2.denominador;
        if (prim < segun)
            res = -1;
        else if (prim > segun)
            res = 1;
        else
            res = 0;
        return res;
    }
    public void reset() {
        numerador = 0;
        denominador = 1;
    }
}