Newsgroup: it.comp.java
Titolo: olimorfismo: che danno se si comporta "troppo" bene!

Risolvendo il seguente esercizio, ho avuto un problema col polimorfismo:
Modificare la classe Libro dell'esercitazione precedente in modo tale che
implementi l'interfaccia Comparable e che implementi il metodo compareTo()
confrontando i libri in base al valore dell'attributo numPagine.
Ridefinire l'implementazione di compareTo() nella sottoclasse Vocabolario in
modo tale che confronti i vocabolari in base al valore dell'attributo
numDefinizioni.
Scrivere quindi una classe OrdinaLibri che riceva in input una lista di
libri (alcuni dei quali possono essere vocabolari), li ordini e stampi il
risultato.
Oltre ad utilizzare l'interfaccia Comparable, si deve utilizzare la classe
VettoreOrdinato.
E' chiaro che non posso toccare le classi Libro, Vocabolario, e
VettoreOrdinato.
La classe OrdinaLibri dovrebbe riempire un array di libri (metodo
riempiArray), seppure tra questi libri ci possono essere vocabolari.
Risolverei tutto se, bypassando il polimorfismo, passassi effettivamente dei
libri al metodo riempiArray (anche nel caso dei vocabolari).
Fare casting non basta, gli oggetti vocabolario "ricordano" sempre di essere
tali.
Il problema è fare ordinamento di libri visto nonostante tra i libri possano
esserci dei vocabolari. Quindi vorrei utilizzare <oggetto
libro1>.compareTo(<oggetto libro2>) ma nel caso in cui l'oggetto1 è un
vocabolario... ho un grosso problema come potrete notare utilizzando le
classi allegate.
Vi prego di non darmi risposte affrettate, anche perchè le ho provate quasi
tutte!!!
ECCO LE CLASSI:
/**
 * Questa classe costriusce libri. Ogni libro è
 * caratterizzato dal numero di pagine.
 * Data di creazione: (08/07/2002 10.37.36)
 * @author: Administrator
 */
import javax.swing.*;
public class Libro implements Comparable
{
 protected int numPagine;
/**
 * Costruttore della classe Libro:
 * esso richiede il numero delle pagine che il libro deve
 * contenere ed esegue il controllo sulla non negatività
 * del numero delle pagine.
 */
public Libro()
{
 super();
 boolean flg;
 do
 {
  int nPag=Integer.parseInt(JOptionPane.showInputDialog(null,"Di quante
pagine deve essere il libro?"));
  if(nPag<0)
  {
   Edita.scrive("Errore","ATTENZIONE!\nIl numero delle pagine deve essere
positivo!",3);
   flg=false;
  }
  else
  {
   setNumPagine(nPag);
   flg=true;
  }
 }while(flg==false);
}
/**
 * Costruttore della classe Libro:
 * esso richiede in input il numero delle pagine che il libro deve
 * contenere e ne setta il valore.
 */
public Libro(int n)
{
 super();
 setNumPagine(n);
}
/**
 * Costruttore della classe Libro:
 * esso richiede il numero delle pagine che il libro deve
 * contenere ed esegue il controllo sulla non negatività
 * del numero delle pagine.
 */
public Libro(String tipo)
{
 super();
 boolean flg;
 do
 {
  int nPag=Integer.parseInt(JOptionPane.showInputDialog(null,"Di quante
pagine deve essere "+tipo+"?"));
  if(nPag<0)
  {
   Edita.scrive("Errore","ATTENZIONE!\nIl numero delle pagine deve essere
positivo!",3);
   flg=false;
  }
  else
  {
   setNumPagine(nPag);
   flg=true;
  }
 }while(flg==false);
}
public int compareTo(Object o)
{
 System.out.println("Sono in compareTo con Object");
 if(o instanceof Libro)
 {
  Libro l=(Libro)o;
  if(this.numPagine>l.numPagine)
  {
   return -1;
  }
  else if(this.numPagine<l.numPagine)
  {
   return 1;
  }
  else
  {
   return 0;
  }
 }
 else
 {
  Edita.scrive("Errore","ATTENZIONE!\nL'oggetto passato in input al
compareTo"+
            " deve essere un' istanza di un oggetto di tipo Libro" +
            "\ninvece è un... " + o ,3);
  return -10;
 }
}
/**
 * Metodo get per la variabile di istanza numPagine.
 * Data di creazione: (08/07/2002 10.52.21)
 */
public int getNumPagine()
{
 return numPagine;
}
/**
 * Metodo che stampa il numero delle pagime del libro.
 * Data di creazione: (08/07/2002 10.55.28)
 */
public void pageMessage()
{
 String messaggio="Il numero di pagine del libro è "+numPagine;
 Edita.scrive("Messaggio",messaggio,2);
}
/**
 * Metodo set per la variabile di istanza numPagine.
 * Data di creazione: (08/07/2002 10.51.13)
 */
public void setNumPagine(int n)
{
 numPagine=n;
}
}
-----------------------------------------
/**
 * Classe utilizzata per l'ordinamento
 * di libri generici in base al numero di pagine.
 * Data di creazione: (09/07/2002 10.25.55)
 * @author: Administrator
 */
public class OrdinaLibri extends VettoreOrdinato
{
 /**
  * Commento del constructor OrdinaLibri.
  */
 public OrdinaLibri(int maxElementi, int curElementi)
 {
  super(maxElementi);
  if(maxElementi>=curElementi)
  {
   riempiArray(curElementi);
  }
  ordina();
 }
 /**
  * Inserire qui la descrizione del metodo.
  * Data di creazione: (09/07/2002 12.25.52)
  */
 public String creaOutput()
 {
  String output="";
  for(int i=0;i<elementi();i++)
  {
   output+=((Libro)leggi(i)).getNumPagine()+", ";
  }
  return output;
 }
 public void riempiArray(int dim)
 {
  int scelta=0;
  boolean flag=false;
  Comparable lib;
  /* scegle a caso se aggiungere un libro o un vocabolario
     e a caso gli passa i parametri */
  for(int i=0; i<dim; i++)
  {
   scelta=0+(int)(Math.random()*2);
   if(scelta == 0 )
   {
    lib=new Libro(1+(int)(Math.random()*1000));
   }
   else
   {
    lib=new
Vocabolario(1+(int)(Math.random()*1000),1+(int)(Math.random()*2000));
   }
   flag=aggiungi(lib);
  }
 }
}
-------------------------------------------
class VettoreOrdinato {
   private Comparable vettore[]; // In questa versione di VettoreOrdinato
        // si possono inserire solo oggetti che
        // implementano l'interfaccia Comparable.
   private int maxElementi;  // Numero massimo di elementi
   private int curElementi;  // Numero di elementi effettivamente presenti
   public VettoreOrdinato (int maxElementi) { // costruttore
   this.maxElementi = maxElementi;
   vettore = new Comparable[maxElementi];
   curElementi = 0;
   }
   public int maxElementi () { return maxElementi; }
   public int elementi () { return curElementi; }
   protected boolean aggiungi (Comparable elemento)
   {
   // aggiunge un elemento se possibile, altrimenti ritorna false
   if (elemento != null && curElementi < maxElementi) {
   vettore[curElementi++] = elemento;
   return true;
   } else
   return false;
   }
   public Comparable leggi (int indice) //  legge un elemento
   {
   if (indice >= 0 && indice < curElementi)
   return (vettore[indice]);
   else
   return null;
   }
   public void ordina ()    //ordina elementi usando 'compareTo()'
   {
    Comparable appoggio;
    for(int i=0; i<curElementi; i++)
  {
System.out.println("vettore["+i+"]="+((Libro)leggi(i)).getNumPagine());
  }
    for(int j=curElementi-1; j>=1; j--)
    {
     for(int i=0; i<j; i++)
     {
         if( (vettore[i].compareTo(vettore[j])) == -1 )
         {
          appoggio=vettore[i];
          vettore[i]=vettore[j];
          vettore[j]=appoggio;
         }
     }
    }
   }
}
----------------------------------
/**
 * Inserire qui la descrizione del tipo.
 * Data di creazione: (08/07/2002 11.02.11)
 * @author: Administrator
 */
 import javax.swing.*;
public final class Vocabolario extends Libro
{
 private int numDefinizioni;
/**
 * Costruttore di default di Vocabolario:
 * chiama il costruttore di Libro che chiede in input
 * la stringa contenente il nome del libro e che all'interno chiederà
 * il numero di pagine del vocabolario; poi chiede
 * il numero di definizioni contenute nel vocabolario e ne setta il valore.
 */
public Vocabolario()
{
 super("Il vocabolario");
 boolean flg;
 do
 {
  int nDef=Integer.parseInt(JOptionPane.showInputDialog(null,"Quante
definizioni contiene il vocabolario?"));
  if(nDef<0)
  {
   Edita.scrive("Errore","ATTENZIONE!\nIl numero delle definizioni deve
essere positivo!",3);
   flg=false;
  }
  else
  {
   setNumDefinizioni(nDef);
   flg=true;
  }
 }while(flg==false);
}
/**
 * Commento del constructor Vocabolario:
 * chiede in input il numero di definizioni
 * contenute nel vocabolario.
 */
public Vocabolario(int nd)
{
 super("Il vocabolario");
 setNumDefinizioni(nd);
}
/**
 * Commento del constructor Vocabolario:
 * chiede in input il numero di pagine e il numero
 * di definizioni del vacabolario.
 */
public Vocabolario(int n, int nd)
{
 super(n);
 setNumDefinizioni(nd);
}
/**
 * Inserire qui la descrizione del metodo.
 * Data di creazione: (08/07/2002 18.13.54)
 */
public int compareTo(Object o)
{
 System.out.println("Sono in compareTo di vocabolario con Object");
/* if(o instanceof Libro)
 {
  System.out.println("Sono in Vocabolario e sto per andare nel compareTo di
Libro");
  return super.compareTo(o);
 }
 else   */
 if(o instanceof Vocabolario)
 {
  Vocabolario l=(Vocabolario)o;
  if(this.numDefinizioni>l.numDefinizioni)
  {
   return -1;
  }
  else if(this.numDefinizioni<l.numDefinizioni)
  {
   return 1;
  }
  else
  {
   return 0;
  }
 }
 else
 {
  Edita.scrive("Errore","ATTENZIONE!\nL'oggetto passato in input al
compareTo"+
            " deve essere un' istanza di un oggetto di tipo Vocabolario" +
            "\ninvece è un... " + o ,3);
  return -10;
 }
}
/**
 * Inserire qui la descrizione del metodo.
 * Data di creazione: (08/07/2002 11.16.30)
 */
public void definitionMessage()
{
 String messaggio="Il numero di pagine del libro è "+numPagine;
 messaggio+=".\nEsso contiene "+numDefinizioni+" definizioni, quindi,";
 messaggio+=" mediamente, ogni pagina contiene ";
 messaggio+=((int)(numDefinizioni/numPagine))+" definizioni.";
 Edita.scrive("Informazioni",messaggio,2);
}
/**
 * Inserire qui la descrizione del metodo.
 * Data di creazione: (08/07/2002 11.08.39)
 */
public int getNumDefinizioni()
{
 return numDefinizioni;
}
/**
 * Inserire qui la descrizione del metodo.
 * Data di creazione: (08/07/2002 11.07.06)
 */
public void setNumDefinizioni(int n)
{
 numDefinizioni=n;
}
}
-------------------------------------------------
/**
 * Inserire qui la descrizione del tipo.
 * Data di creazione: (21/06/2002 10.17.05)
 * @author: Administrator
 */
import javax.swing.*;
public class Edita {
/**
 * Commento del constructor Edita.
 */
public Edita() {
 super();
}
//**************************************************************************
***********/
/*               METODO PER LA VISUALIZZAZIONE DELL'OUTPUT.
*/
/*
*/
/*  NOME METODO:                scrive(String intestazione, String
messaggio,int n)   */
/*  SIGNIFICATO DEI PARAMETRI:  intestazione= titolo della finestra;
*/
/*                              frase= messaggio da visualizare;
*/
/*                              n= identificatore di messaggio; vale:
*/
/*                                   0     se si desidera una finestra senza
icone    */
/*                                         e con titolo "messaggio";
*/
/*                                   1     se si desidera una finestra senza
icone    */
/*                                         e con titolo "intestazione";
*/
/*                                   2     se si vuole dare un'informazione
*/
/*                                   3     se si deve segnalare un errore;
*/
/*                                   4     se si vuole richiamare
l'attenzione su     */
/*                                         un particolare;
*/
/*                                   5     se si deve porre una domanda;
*/
//**************************************************************************
***********/
   public static void scrive(String intestazione, String frase,int n)
   {
       switch(n)
       {
        case 0:
             JOptionPane.showMessageDialog(null,frase);
             break;
        case 1:
JOptionPane.showMessageDialog(null,frase,intestazione,JOptionPane.PLAIN_MESS
AGE);
             break;
        case 2:
JOptionPane.showMessageDialog(null,frase,intestazione,JOptionPane.INFORMATIO
N_MESSAGE);
             break;
        case 3:
JOptionPane.showMessageDialog(null,frase,intestazione,JOptionPane.ERROR_MESS
AGE);
             break;
        case 4:
JOptionPane.showMessageDialog(null,frase,intestazione,JOptionPane.WARNING_ME
SSAGE);
             break;
        case 5:
JOptionPane.showMessageDialog(null,frase,intestazione,JOptionPane.QUESTION_M
ESSAGE);
             break;
        default:
             frase="ATTENZIONE! Il terzo parametro inserito nell'invocazione
del metodo non è esatto!";
             intestazione="Errore";
JOptionPane.showMessageDialog(null,frase,intestazione,JOptionPane.ERROR_MESS
AGE);
             break;
       }
   }
}
---------------------------------------------------
/**
 * Inserire qui la descrizione del tipo.
 * Data di creazione: (09/07/2002 12.16.15)
 * @author: Administrator
 */
import javax.swing.*;
public class TestOrdinaLibri {
/**
 * Commento del constructor TestOrdinaLibri.
 */
public TestOrdinaLibri() {
 super();
}
/**
 * Inserire qui la descrizione del metodo.
 * Data di creazione: (09/07/2002 12.16.35)
 * @param args java.lang.String[]
 */
public static void main(String[] args)
{
 int nMax=Integer.parseInt(JOptionPane.showInputDialog(null,
          "Quanti libri può contenere il tuo scaffale?"));
 int nLibri;
 boolean flg;
 do
 {
  nLibri=Integer.parseInt(JOptionPane.showInputDialog(null,
          "Quanti libri devi inserire nello scaffale?"));
  if( nLibri > nMax)
  {
      Edita.scrive("Errore","ATTENZIONE!\nNon puoi inserire"+
                " più di "+nMax+" libri!",3);
      flg=false;
  }
  else
  {
      flg=true;
  }
 }while(flg==false);
 OrdinaLibri app=new OrdinaLibri(nMax,nLibri);
 Edita.scrive("Risultato finale","I libri ordinati sono rispettivamente di
\n"+
           app.creaOutput()+"\npagine.",2);
}
}

Errata Corrige dell'oggetto!
Inoltre volevo far notare che ci sono, nel thread precedente, i sorgenti
delle classi utilizzate.
Resto in attesa delle risposte del newsgroup.
Ciao.