Uso de clases abstractas

MIRL
22 de Enero del 2009
Hola!

Tengo que crear una clase abstracta pero no entiendo muy bien cómo hacerlo para luego poder hacerme un array con objetos de esta clase, explico el tema:

Si yo tengo:

public abstract class Figura {
protected int alto;
protected int ancho;

public Figura(int alto, int ancho) {
this.alto = alto; this.ancho = ancho;
}

public abstract int area();
}

public class Rectangulo extends Figura {
private Color color;

public Rectangulo(int alto, int ancho, Color color) {
this.alto = alto; this.ancho = ancho; this.color = color;
}
}

¿Cómo haría en mi main para guardar objetos de tipo Figura en un array (usaré ArrayList y tendré rectángulos, triángulos, etc) e identificar los atributos de cada uno otorgados por la subclase?

¿Estoy enfoncando mal el problema?

Muchas gracias por adelantando.

havalle
22 de Enero del 2009
Hola,

Mira creo que hasta ahora lo estas enfocando bien, pero por las dudas voy a comentar todo lo que veo acerca de lo que has puesto, y espero que te sirva de ayuda.

No te olvides que en la clase Rectangulo (y en las futuras clases Triangulo, Cuadrado, o las que sean que extiendan Figura) debes definir el metodo abstracto area().

Otra cosa es el constructor en las clases que extiendan figura, por ejemplo en tu clase Rectangulo, la forma correcta sería:

public Rectangulo(int alto, int ancho, Color color)
{
//tienes que llamar al constructor de Figura
super(alto, ancho);
this.color = color;
}


Luego el tema del ArrayList, pues sería algo como esto;

ArrayList<Figura> arr = new ArrayList<Figura>();

y luego le agregas todos los elementos que necesites (esta por supuesto es solo una forma, tu lo haras de la manera en que recibas los datos, ya sea desde una base de datos, un archivo, etc ... también lo siguiente es suponiendo que tengas todas esas clases creadas, y de forma parecida a Rectangulo):

arr.add(new Rectangulo(1, 1, new Color(222)));
arr.add(new Triangulo(1, 1, new Color(222)));
arr.add(new Cuadrado(1, 1, new Color(222)));

Pero eso sí, no te olvides que al declarar el Array de tipo Figura, por mas que este pueda recibir cualquier clase que extienda de Figura, SOLO PODRÁ ACCEDER A LOS DATOS QUE ESTAN DECLARADOS EN ESA CLASE(ES DECIR FIGURA).

Por ejemplo el siguiente loop es correcto:

for (Figura f : arr)
{
f.alto = 2;
int area = f.area();
}


pero el siguiente no es correcto:

for (Figura f : arr)
{
f.alto = 2;
int area = f.area();
f.color = new Color(111); //esto está mal!!!
}

Si bien en tu post lo declaras como private, no se podría acceder ni aunque lo declararas como public, porque esta declarado en Rectangulo, y no en Figura. Por mas que lo declares en todas las clases que extienden Figura, igualmente al no estar en Figura no lo vas a poder utilizar.
En este caso la manera sería hacerle un cast al objeto y luego utilizarlo, ej:

(Supongamos que estamos dentro del loop anterior y sabemos que el objeto actual es de tipo Rectangulo)

f.alto = 2;
int area = f.area();
((Rectangulo)f).color = new Color(111);

pero esto ya seria demasiado, quizas te convenga declarar el Color dentro de Figura, y utilizarlo cuando te convenga, y si no lo necesitas darle un valor por defecto, o algo parecido, a menos que sepas seguro cuando uno de los objetos Figura en realidad sea del tipo Rectangulo.

Creo que eso es todo lo que se me viene a la cabeza, espero haberte ayudado.

Saludos, Hernán.

MIRL
22 de Enero del 2009
ok, muchas gracias, creo que lo he entendido, y me parece bastante interesante lo que comentas de declarar los atributos en la clase abstracta, lo analizaré (porque no es solo uno los que difieren de una figura a otra precisamente)

El tema está en el casting, que obviamente es imposible saber de qué tipo va a ser el objeto almacenado.

Quizá lo que añada sea un chivato que indique el tipo del objeto y con eso hacer el casting mediante un switch, por ejemplo...

Gracias de nuevo, me has ayudado a entenderlo mejor ;)