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.
siiii
ResponderEliminarmuchas gracias esta excelente!
ResponderEliminartal vez me ayudas con la clase main para correr todas las clases?
Genial. Muchas gracias por tu aporte. Es realmente muy didáctico.
ResponderEliminar