Newsgroup: it.comp.java
Titolo: Come posso fare?

Premetto la mia scarsa conoscenza di questo linguaggio.
Ecco la domanda.
Volevo fare una classe padre di nome : Figura
E poi delle classi figlie come cerchio, quadrato, ecc.
Ora come posso far sio che io possa creare un oggetto Figura che si tramuta
automaticamente in un cerchio o quadrato a seconda dei dati di ingresso?
Grazie

Allego il codice che ho scritto :
Questa è la classe in cui creo l'oggetto Figura
------------------------------------------------------------------------
import Figura;
public class lavagna
{
 public static void main (String[] args)
 {
  Figura[] lista;
  lista = new Figura[0];
  Figura elemento1 = new Figura(1, 3, 3, 3);
  lista[0] = elemento1;
  System.out.println ("       +-CERCHIO-+           ");
  System.out.println (""+ lista[0]);
 }
}
------------------------------------------------------------------------
Questa è figura
------------------------------------------------------------------------
public abstract class Figura
{
 protected int color, x, y;
 protected String coloreFigura;
 public Figura (int color, int centroX, int centroY)
 {
 x = centroX;
 y = centroY;
 if (color == 1)
  coloreFigura = "Nero";
 else coloreFigura = "Grigio";
 }
 public abstract String toString ();
}
------------------------------------------------------------------------
E questa è cerchio.
------------------------------------------------------------------------
import Figura;
public class Cerchio extends Figura
{
 private int radius;
 public Cerchio (int colore, int cX, int cY, int r)
 {
  super (colore, cX, cY);
  radius = r;
 }
 public String toString ()
 {
  return "FIGURA : cerchio \nCENTRO : "+x+","+y+" \nCOLORE : " +
coloreFigura + "\nRAGGIO : "+radius;
 }
}


Per iniziare forse dovresti ribaltare le cose:
Ovvero istanziare oggetti di qualunque natura, ma trattarli come "Figura"?
Ti consiglio di leggerti "Thinking in Java" (
www.mindview.com
)
Ciao!
Giuseppe

 Allego il codice che ho scritto :
Bo...Prova a partire dall'altra parte. 
Io l'avrei scritto cosi':
public interface Figura
{
public static final int CERCHIO=-1;
public static final int QUADRATO=-2;
public static final int GRIGIO = 0;
public static final int NERO = 1;
public static final int VERDE = 2;
public int getType();
public String toString();
}
class Cerchio implements Figura
{
private int color,x,y;
private int raggio;
private int type=Figura.CERCHIO;
public Cerchio(int color, int x, int y, int raggio)
{
this.color = color;
this.x=x;
this.y=y;
this.raggio=raggio;
}
public int getType()
{
return type;
}
public String toString()
{
String colorType ="";
switch (color)
{
case Figura.NERO: { // metto le graffe per leggibilità
                  colorType="Nero";
                  break; }
case Figura.VERDE: { // metto le graffe per leggibilità
                  colorType="Verde";
                  break; }
default: { // metto le graffe per leggibilità
                  colorType="Grigio";
                  break; }
}
String s= "FIGURA : cerchio \nCENTRO : "+x+","+y+" \nCOLORE : "+ colorType + 
"\nRAGGIO : "+raggio;
return color;
}
 
class Quadrato implements Figura
{
private int color,x,y;
private int type=Figura.QUADRATO;
public Quadrato(int color, int x, int y)
{
this.color = color;
this.x=x;
this.y=y;
}
public int getType()
{
return type;
}
public String toString()
{
String colorType ="";
switch (color)
{
case Figura.NERO: { // metto le graffe per leggibilità
                  colorType="Nero";
                  break; }
case Figura.VERDE: { // metto le graffe per leggibilità
                  colorType="Verde";
                  break; }
default: { // metto le graffe per leggibilità
                  colorType="Grigio";
                  break; }
}
String s= "FIGURA : quadrato \nLATI : "+x+","+y+" \nCOLORE : "+ colorType;
return color;
}
Classe principale:
public class Lavagna
{
public static void main (String[] args)
  {
   Figura[] lista;
   lista[0] = new Cerchio(1, 3, 3, 3); 
   lista[1] = new Quadrato(1,4,2);
 
   for (int i=0; i<lista.length; ++i)
        System.out.println("Info Figura: "+lista[i].toString());
 
 }
}
-- 
You should be mine.

Non ho ben capito.
Cmq il mio intento è quello di creare oggetti di tipo figura che tuttavia
sono in realtà cerchi o quadrati o triangoli, o ecc.
Voglio che tutti possano essere creati facendo New Figura e non New
Quadrato, ecc...
E che tutti possano essere stampati con lo stesso comando.

 E che tutti possano essere stampati con lo stesso comando.
Se hai un metodo (ad esempio print()) definito nella classe Figura e
tutte le figure (Quadrato, Cerchio, etc.) derivano da questa, anche
questa verranno stampate col emtodo print() (eventualmente facendone
l'overriding).
-- 
Lucio Benfante
Brainbench MVP for Java 1
http://www.brainbench.com
MyTranscript: 
http://www.brainbench.com/transcript.jsp?pid=167064

 ingresso? 
Riassumo rapidamente:
Crei una interfaccia Figura
Crei le classi Cerchio, Quadrato, che implementano l'interfaccia.
Crei una classe FiguraFactory con un unico metodo statico create(), che 
restituisce Figura e instanzia la classe concreta a seconda del parametro 
passato.

 automaticamente in un cerchio o quadrato a seconda dei dati di ingresso?
Hai già fatto la classe Cerchio che estende figura, adesso non ti resta che
istanziarla così:
  Figura disegno = new Cerchio(1,2,3,4);
Supponendo che tu abbia anche la classe Quadrato puoi fare:
  Figura disegno2 = new Quadrato(1,2,3,4);
e quindi gestire insieme quadrati e cerchi così:
  public class lavagna
  {
     public static void main (String[] args)
    {
       Figura[] lista;
       lista = new Figura[2];
       lista[0] = new Cerchio(1, 3, 3, 3);
       lista[1] = new Quadrato(1,2,3,4);
     }
  }
Se poi nella classe figura inserisci un metodo vuoto del tipo:
  public double Area()
  {
    return 0;
  }
e nella classi Cerchio e Quadrato lo sovrascrivi facendogli restituire
l'area
  (in Quadrato)
  public double Area()
  {
     return lato*lato;
  }
  (in Cerchio)
  public double Area()
  {
     return radius*radius*3.14; // radius vuol dire raggio, vero?
  }
puoi anche gestire gli oggetti figure così:
   public static void main (String[] args)
  {
     Figura[] lista;
     lista = new Figura[2];
     double areaTotale;
     lista[0] = new Cerchio(1, 3, 3, 3);
     lista[1] = new Quadrato(1,2,3,4);
     areaTotale = lista[0].Area() + lista[1].Area();
     System.out.println("Area totale: "+areaTotale);
   }
In questo modo puoi trattare tutti i tipi di figure diverse (Cerchio
Quadrato Triangolo) come se fossero figure qualunque, ma mantenedo distinte
le loro differenze (Area perimetro...)
Era questo quello che volevi? Spero di essere stato abbastanza chiaro.

Huan è quello che c'è andato più vicino.
Ma non c'è il modo di fare questo ?
Figura disegno = new Figura (1,2,3,4);
a seconda del numero di dati di ingresso o dei tipi di dati il compilatore
riesce a decidere autonomamente il tipo di figura da creare?
Devo forse dichiarare la classe Figura abstract?

 Devo forse dichiarare la classe Figura abstract?
No, non serve a niente.
La cosa piu' vicina a quello che vuoi fare tu e' l'implementazione
(parziale) del pattern Abstract Factory.
Non e' il caso qui di divagare su cosa sono i pattern. Provo a mostrarti
come potrebbe essere risolto il tuo problema con questo pattern.
Si tratta di avere una classe con dei metodi che si occupano di costruire
famiglie di oggetti. In questo caso specifico, il pattern e' ridotto,
dato che la famiglia di oggetti da costruire e' una sola, quindi non c'e'
bisogno di una factory astratta, ma si puo' partire direttamente con una factory
concreta (e addirittura con metodi statici).
Potrebbe essere una cosa del genere:
(le varie classi delle figure derivano tutte dalla classe Figura)
public class FigureFactory {
  public static Figura creaQuadrato(...) {
    return new Quadrato(...);
  }
  public static Figura creaCerchio(...) {
    return new Cerchio(...);
  }
 
  ...
}
Ora per creare delle figure scriverai qualcosa del genere:
Figura f1 = FigureFactory.creaQuadrato(...);
Figura f2 = FigureFactory.creaCerchio(...);
Niente vieta che la classe factory sia la stessa classe Figura, ma io lo
eviterei, dato che la lega troppo alle sue sottoclassi. Pensaci: Quadrato
estende Figura, quindi Quadrato sa che esiste la classe Figura, ma la
classe Figura potrebbe ignorare che esiste la classe Quadrato. Se Figura
fosse la classe factory, ogni volta che viene creata una nuova sotto
classe di Figura, occorre modificare anche Figura stessa. Modifica per
modifica, molto meglio avere questa forte dipendenza in un'altra classe.
Niente vieta anche che il nome dei metodi sia sempre lo stesso, ad
esempio tanti creaFigura in overloading, ma devi essere in grado di discriminare
in base al numero, tipo e ordine dei loro parametri:
public class FigureFactory {
  public static Figura creaFigura(<parametri per il quadrato>) {
    return new Quadrato(...);
  }
  public static Figura creaFigura(<parametri per il cerchio>) {
    return new Cerchio(...);
  }
 
  ...
}
...quindi:
Figura f1 = FigureFactory.creaFigura(<parametri per il quadrato>);
Figura f2 = FigureFactory.creaFigura(<parametri per il cerchio>);
Io, non ne vedo il vantaggio, dato che comunque devi scrivere codice
differente per creare oggetti di dipo diverso. Inoltre e' meno chiaro,
dato che non puoi capire cosa effettivamente viene creato semplicemente
dal nome del metodo, ma devi leggerti la documentazione del particolare
metodo creaFigura (quello con gli specifici parametri passati).
Un'altra possibile soluzione e' quella di avere un'unico metodo
creaFigura (quindi niente overloading), che puo' creare tutti i tipi
di figura, in base a dei parametri (sempre dello stesso tipo, numero e ordine).
Ad esempio:
public class FigureFactory {
  public static Figura creaFigura(String tipoFigura, Object[] params) {
    if (tipoFigura.equals("Quadrato")) {
      return new Quadrato(params[0], params[1], params[2], params[3]);
    } else if (tipoFigura.equals("Cerchio")) {
      return new Quadrato(params[0], params[1], params[2]);
    }
    ....
  }
}
...quindi:
Figura f1 = FigureFactory.creaFigura("Quadrato", <array di parametri per il quadrato>);
Figura f2 = FigureFactory.creaFigura("Cerchio", <array di parametri per il cerchio>);
Personalmente te la sconsiglio, dato che perdi tutti i vantaggi del
controllo del tipo fatto dal compilatore.


 significati, ne' gliene puoi assegnare tu di nuovi.
quindi new Figura è da escludere.
Il fatto è che se vuoi un quadrato, puoi girarti tutte le classi delle jdk,
ma da qualche parte new Quadrato lo devi mettere.
E' possibile stabilire il tipo della figura dai parametri di ingresso, ma
non mi sembra molto pratico perché ogni figura dovrebbe avere una sequenza
di parametri diversi. Così non potrai avere un gran numero di figure
diverse.
Comunque, se proprio vuoi usare questo procedimento, puoi farti un metodo
che distingue i parametri.
Ad esempio se abbiamo il costruttore della classe Cerchio che vuole quattro
interi e quello della classe Rettangolo che ne vuole cinque puoi fare una
cosa del tipo:
  // Con gli stessi parametri del cerchio restituisco un'istanza di Cerchio
  public Figura generaFigura(int colore, int cX, int cY, int r)
  {
     return new Cerchio(colore,cX,cY,r);
  }
  // Con gli stessi parametri del rettangolo restituisco un'istanza di
Rettangolo
  public Figura generaFigura(int colore, int aX, int aY, int bX, int bY)
  {
    return new Rettangolo(colore,aX,aY,bX,bY);
  }
Adesso puoi tranquillamente fare:
  lista[0] = new generaFigura(1, 3, 3, 3);
  lista[1] = new generaFigura(1, 2, 3, 4, 5);
lista[0] è a tutti gli effetti un cerchio, tanto come lista[1] è un
rettangolo quindi potrai anche fare
  areaTotale = lista[0].Area() + lista[1].Area();
  System.out.println("Area totale: "+areaTotale);
ottenendo il calcolo corretto.
Spero, questa volta, di aver trovato la soluzione giusta.

 
generaFigura(...) sono metodi non classi, quindi non ne puoi crearne
un'istanza con new, ma li devi invocare usando un reference ad un oggetto
della classe che li definisce, o definirli statici e usare direttamente
il nome della classe.


 generaFigura(...) sono metodi non classi, quindi non ne puoi crearne
Ops, chiedo scusa, ho commesso un piccolo errore di distrazione...
  lista[0] = new generaFigura(1, 3, 3, 3);
  lista[1] = new generaFigura(1, 2, 3, 4, 5);
                 ^^^
quella new non so proprio come ci sia finita, ma basta toglierla:
  lista[0] = generaFigura(1, 3, 3, 3);
  lista[1] = generaFigura(1, 2, 3, 4, 5);
Ecco fatto: così funziona!
Dai, perdonatemi! Un errorino ogni tanto scappa a tutti, soprattutto quando
non puoi compilare quello che scrivi! :-)

 Ecco fatto: così funziona
Si ma non e' ok, perche generaFigura ha visibilita solo all'interno del
package: sarebbe meglio se generaFigura fosse static.
Il tuo generaigura e' molto simile a un Factory.


 Il tuo generaigura e' molto simile a un Factory.
Beh, io ho solo descritto il metodo, poi decide lui dove e come metterlo.
Mica conosco tutto il suo progetto. Comunque così risolvi il problema
semplicemente in due righe.