|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Bannato
Iscritto dal: Mar 2004
Città: Roma
Messaggi: 2682
|
[JAVA] Domande su questo esercizietto
Ciao,
a giorni avrò un esame di Java all'uni...vi posto il testo di questo esercizietto di un vecchio compito e qualche idea (+ molti dubbi) su come impostarlo. E' un esame di linguaggi di programmazione più che di Java...di Java abbiamo fatto poco (solo i costrutti base), l'esercizio è semplice...più che altro è la progettazione dove la proff è pignola... Problema 1. Si richiede il progetto di un tipo astratto di dati ArticoloInSupermercato, e l’implementazione della corrispondente classe Java, che rappresenta e gestisce gli articoli in vendita in un supermercato. Ciascun articolo deve recare le informazioni relative al suo nome, al suo prezzo ed alla quantità presente nel negozio. Inoltre, ciascun articolo deve registrare anche il reparto del supermercato cui è assegnato (ad esempio, ortofrutta, macelleria, pulizia casa, ….). I reparti caratterizzano completamente il supermercato e devono essere noti prima che la gestione degli articoli possa iniziare. Si osservi come, al momento della creazione di un oggetto di tipo , sia necessario controllare che esso appartenga ad un reparto presente nel supermercato. Le operazioni richieste per il tipo di dato sono: a) accesso (in lettura) alle caratteristiche di un oggetto; b) test di uguaglianza di due oggetti; c) rappresentazione di un oggetto in forma di stringa. La prima cosa che vuole è sto benedetto tipo di dato astratto che è una rappresentazione insiemistica di cosa deve rappresentare la classe che poi implementerò, tocca rappresentare 3 insiemi: V (insieme degli elementi rappresentati dalla classe), O (insieme delle operazioni sugli oggetti della classe), C (insieme delle eventuali costanti). Il primo dubbio su come fare sta classe (e quindi sul suo tipo di dato astratto) è la storia dei reparti perchè dice che i reparti caratterizzano completamente il supermercato e devono essere noti prima che la gestione degli articoli possa iniziare...quindi la prima cosa che mi viene in mente è che siano rappresentati mediante ad un array di classe che deve essere inizializzato prima che gli oggetti della classe vengano creati...ci può stare come idea? Per il tipo astratto di dato quindi direi: V(reparto) = {articoli in vendita nel supermercato} dove metto "reparto" tra () perchè l'insieme V dipende dalla lista dei reparti O(reparto) = 1) accesso(caratteristica) che restituisce la caratteristica richiesta dell'oggetto ricevente 2) equals (ridefinisco il metodo equals nella mia classe) 3) toString (ridefinisco il metodo toString nella mia classe) C = 0 (insieme vuoto: non ci sono costanti significative da rappresentare) Quindi imposterei la progettazione della classe dichiaranto un vettore di reparti come static (dove magari potrebbe essere un vettore di stringhe: "ortofrutta", "macelleria", "pulizia casa",...) Poi dichiarerei semplicemente come private le variavili di istanza dei possibili oggetti che dovrebbero essere: nomeProdotto di tipo String, prezzo di tipo double, quantità di tipo int ed infine reparto di tipo intero che mi indica la posizione nel vettore static reparti e mi identifica univocamente il reparto di appartenenza del prodotto. Per farla semplice posso inizializzare direttamente nel codice il vettore reparti oppure potrei settarlo inizialmente a null e definire un appostito metodo che me lo inizializzi. Se scegliessi queta seconda strada nel costruttore degli oggetti dovrei eseguire un check che controlla se il vettore reparti è già stato inizializzato o se è ancora a null...se è ancora a null restituisce un messaggio di errore e termina (le eccezioni le abbiamo viste solo in teoria e le vedremo in Java il prossimo semestre al prossimo corso). Ci può stare come analisi preliminare per la rappresentazione della mia classe? Stò un po' nel panico per questo esame ![]() Grazie Andrea |
![]() |
![]() |
![]() |
#2 |
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
Se le avete studiate puoi usare le enum che sono lo strumento + indicato per gestire i reparti nel tuo caso.
Per quanto riguarda l'inizializzazione lo puoi fare all'interno della classe Supermercato nel costruttore secondo me...
__________________
![]() |
![]() |
![]() |
![]() |
#3 | |
Bannato
Iscritto dal: Mar 2004
Città: Roma
Messaggi: 2682
|
Quote:
Di solito o le inizializza a mano nel codice oppure le fà inizializzare ad un metodo di classe... Cmq il resto dell'analisi sulla proggettazione della struttura della classe ci può stare? Il tipo di dato astratto è ok? (anche se inizio a pensare che sia una cosa che fà solo lei perchè molte persone con cui ho parlato manco sapevano che era...) |
|
![]() |
![]() |
![]() |
#4 | |
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
Quote:
![]() Per quanto riguarda il vettore visto che hai detto che è noto a priori la cosa + logica è memorizzarla in una variabile private static final String[] da inizializzare dunque immediatamente nella classe Supermercato. Per quanto riguarda il tipo di dati astratto non ho capito se intendi una classe di tipo abstract o un interface... a quanto ho capito mi pare + corretta un'interface dato che non credo tu abbia dei metodi comuni con altri sottotipi.. o meglio.. fare un tipo astratto ed un unico sottotipo imho non ha alcun senso, ma a questo punto io userei un interface al posto di una classe abstract e poi lascerei l'implementazione dei metodi alla classe figlia.... Ah, e a questo punto io memorizzarei all'interno dell'articolo direttamente il nome come stringa e non l'indice del vettore perchè altrimenti dovresti avere accesso dall'articolo all'elenco dei reparti, che, a quanto ho capito, è una cosa che non gli compete, e quindi andresti contro il principio dell'encapsulation.
__________________
![]() |
|
![]() |
![]() |
![]() |
#5 |
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
mmm..
mi sa che ho detto una cazzata perchè con l'interface non puoi memorizzare le variabili nella classe padre quindi mi sa che ti serve una abstract class ![]()
__________________
![]() |
![]() |
![]() |
![]() |
#6 | |
Bannato
Iscritto dal: Mar 2004
Città: Roma
Messaggi: 2682
|
Quote:
Lei vuole che definiamo un tipo di dato astratto cioè che in fase di progettazione (prima di scrivere il codice) definiamo formalmente 3 insiemi: V = INSIEME DELLE ENTITA' RAPPRESENTATE DALLA MIA CLASSE O = INSIEME DEGLI OPERATORI SU QUELLA CLASSE. C = INSIEME DELLE VENTUALI COSTANTI SIGNIFICATIVE PER LA CLASSE. Se ho delle variabili di classe che sono fissate a priori, alora le entità che rappresenterà la mia classe dipenderanno da tali variabili e avrò qualcosa tipo: V(variabili classe) = {descrizione} A me sà tanto di pippa mentale tutto ciò...però non farglielo equivale alla bocciatura... ![]() |
|
![]() |
![]() |
![]() |
#7 |
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
ah ok..
ora mi quadra.. avevo inteso "tipo di dati astratto" proprio come "classe di tipo abstract" ![]() A questo punto direi di inserire il vettore dei reparti nell'insieme delle costanti significative C. ...cmq che pipponi mentali per la progettazione devo dire.. ![]() Ma progettare tutto con UML non sarebbe stato meglio? ![]() (a parte il fatto che odio anche quello essendo un patito del continous design.. ma quanto meno sarebbe stato + utile mi sa ![]()
__________________
![]() |
![]() |
![]() |
![]() |
#8 | |
Bannato
Iscritto dal: Mar 2004
Città: Roma
Messaggi: 2682
|
Quote:
![]() CMQ no le costanti lei intende un'altra cosa...ti faccio un esempio: hai una classe che gestisce Rettangoli mediante i due vertici opposti sulla diagonale principale...per esempio potresti voler definire nella tua classe la costante significativa che indica il rettangolo degenere (che ha i 2 vertici in (0,0)) Ma cmq è sempre una descrizione logica e non implementativa...perchè questo tipo did ati astratti non deve avere nulla a che fare con l'implementazione della classe e non deve fare riferimento ad array o variabili o altre cose di Java....per uno stesso tipo di dati astratti potrei tirarne fuori 10 di implementazioni pratiche diverse...bel segone mentale ve? Però secondo la proff...senza non si programma...e se non glielo fai come cosa preliminare BOCCIATO :-/ Ultima modifica di D4rkAng3l : 29-01-2009 alle 12:16. |
|
![]() |
![]() |
![]() |
#9 |
Bannato
Iscritto dal: Mar 2004
Città: Roma
Messaggi: 2682
|
Classe Java
Rispetto all'esercizio proposto prima...va bene questa classe Java che ho scritto? (poi avrei un problemino a ridefinire il metodo equals...se qualcuno mi dà una mano gliene sono grato.
Codice:
public class ArticoloInSupermercato{ private static String [] reparti = null; // Array di stringhe di classe: rappresenta i reparti del supermercato private String nome_Articolo; // Nome dell'articolo in vendita, inizialmente a ull private double prezzo_Articolo; // Prezzo dell'articolo in vendita private int quantita_Articolo; // Numero di oggetti in vendita per un certo articolo private int indice_Reparto; // Indice di identificazione del reparto nell'array di classe reparti /** METODO DI CLASSE Inizializza(): inizializza il vettore di classe di stringhe reparti con i nomi dei reparti presenti nel supermercato. @param un vettore di stringhe che contiene i nomi dei reparti del supermercato @return void */ public static void Inizializza(String [] T){ int i; if(reparti == null){ // Se la classe non è stata ancora inizializzata for(i=0; i<T.length; i++) reparti[i] = T[i]; // Copia i riferimenti alle stringhe del vettore parametro T nel vettore reparti } else System.err.println("ERRORE: La classe ArticoloInSupermercato è già stata inizializzata"); } /** COSTRUTTORE: Inizializza tutte le variabili di istanza e crea un nuovo oggetto istanza della classe. @param nome di tipo String @param prezzo di tipo double @param quantita di tipo int @param indice di tipo int @return il riferimento ad un oggetto di tipo ArticoloInSupermercato */ public ArticoloInSupermercato(String nome, double prezzo, int quantita, int indice){ if(reparti != null){ // Se la classe è già stata inizializzata crea l'oggetto ed inizializza le sue variabili di istanza nome_Articolo = nome; // Metti il riferimento della stringa nome in nome_Articolo prezzo_Articolo = prezzo; // Copia il valore double di prezzo in prezzo_Articolo quantita_Articolo = quantita; // Copia il valore int di quantita in quantita_Articolo indice_Reparto = indice; // Copia il valore int di indice in indice_Reparto } else // Altrimenti restituisci un messaqggio di errore e non fare nulla System.err.println("ERRORE: la classe non è stata ancora inizializzata, impossibile creare l'oggetto"); } /* METODI DI ACCESSO AI DATI: */ /** getNome: restituisce al chiamante il valore contenuto nel campo nome dell'oggetto ricevente @param void @return una stringa contenente il nome del prodotto */ public String getNome(){ return nome_Articolo; // Ritorna al chiamante il riferimento alla stringa contenente il nome dell'articolo } /** getPrezzo: restituisce al chiamante il valore contenuto nel campo prezzo dell'oggetto ricevente @param void @return una double contenente il prezzo del prodotto */ public double getPrezzo(){ return prezzo_Articolo; // Ritorna al chiamante il riferimento alla stringa contenente il nome dell'articolo } /** getQuantita: restituisce al chiamante il valore contenuto nel campo prezzo quantita dell'articolo @param void @return un int contenente il numero di prodotti per uno specifico articolo */ public int getQuantita(){ return quantita_Articolo; } /** getRepartp: restituisce al chiamante il valore rappresentante l'indice nell'array dei reparti del supermercato @param void @return un int che rappresenta l'indice nell'array dei reparti del supermercato */ public int getReparto(){ return indice_Reparto; } /* METODI DI UTILITA' */ /** METODO toSting: Restituisce al chiamante una stringa contenente i dati contenuti nelle variabili di istanza di un oggetto. @param void @return un oggetto di tipo String che contiene i dati delle variabili di istanza dell'oggetto ricevente sotto forma di stringa */ public String toString(){ String Risposta = "Il nome dell'articolo è: " + nome_Articolo + "Il prezzo è: " + prezzo_Articolo + "Nel supermercato ci sono tot pezzi: " + quantita_Articolo + "L'articolo appartiene al reparto: " + reparti[indice_Reparto]; return Risposta; } /** METODO EQUALS: ridefinisco il metodo equals per confrontare due oggetti istanza della classe ArticoliInSupermercato @parm prodotto di tipo ArticoloInSupermercato da confrontare con l'oggetto ricevente il messaggio @return esito di tipo boolean: TRUE se i due oggetti sono uguali, FALSE altrimenti. public boolean equals(ArticoloInSupermercato prodotto){ boolean esito = this.nome_Articolo == prodotto.getNome */ } ho qualche dubbio sul fatto che avendo dichiarato la variabile nome_Articolo come String possano succedere casini ad esempio con il metodo getNome che ritorna al chiamante il riferimento a quella stringa...in teoria non credo che sia un problema in quanto le stringhe dovrebbero essere oggetti immutabili (nel senso che se provo a modificarlo non si modifica quella stringa ma se ne crea un'altra) quindi non dvorebbe fare problemi... Il problema a scrivere il metodo equals() (che mi dovrebbe confrontare l'oggetto ricevente con l'oggetto referenziato dal parametro) sempre per quanto concerne le stringhe...come faccio a confrontare 2 stringhe? se in tale metodo faccio: this.nome_Articolo = Prodotto.nome_Articolo non stò semplicemente confrontando dei riferimenti a stringhe (e non le stringhe vere e proprie)...come posso implementarlo? C'è qualche problema di sicurezza nella mia classe? Per favore...l'esame si avvicina sempre più... Tnx Andrea |
![]() |
![]() |
![]() |
#10 |
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
Allora un pò di cose:
1) togli quei maledetti underscore dal nome delle variabili! ![]() ![]() 2) Passando tutto il vettore dei reparti alla classe Articolo stai violando il principio di encapsulation dato che l'articolo dovrebbe avere coscienza solo del reparto in cui è e non gliene frega niente del nome di tutti i reparti. 3) Per confrontare le stringhe in java non si puù usare == come hai giustamente notato, ma si deve usare il metodo .equals o .equalsIgnoreCase per confronti non case sensitive (ma non mi pare il tuo caso). 4) Nel costruttore non ti serve controllare se la classe è già stata inizializzata perchè esso viene invocat osolo la prima volta alla creazione dell'istanza. Quel controllo avrebbe senso solo quando si usa il Factory Pattern e qualche altro design pattern simile. 5) io chiamerei le variabili private direttamente nome, prezzo e quantità dato che aggiungere come suffisso Articolo è ridondante. Per l'inizializzazione in quel caso basterebbe scrivere nel costruttore: Codice:
this.nome = nome; this.prezzo = prezzo; this.quantità = quantità; ![]() 7) Nell'equals non puoi concatenare gli operatori di confronto ma devi usare l'operatore &&, inoltre non hai utilizzato l'operatore di confronto (==) ma quello di assegnazione (=) 8) Nel toString puoi scrivere direttamente return "vattelapesca" + cazziemazzi + quellochevuoi senza crearti la variabile temporanea Risposta. E comunque le variabili vanno scritte con la prima iniziale minuscola e non maiuscola ![]() mmm.. mi pare che x ora basti così... sistema 'ste cose e poi vediamo se c'è altro. ![]()
__________________
![]() |
![]() |
![]() |
![]() |
#11 | |
Bannato
Iscritto dal: Mar 2004
Città: Roma
Messaggi: 2682
|
Quote:
I get li ho scritti a mano...la proff ci ha VIETATO di usare eclips per questo primo esame e ci fà usare un editorino scemo (Crimosn editor). mmm mmm mmm la storia di non passare il vettore...booo...lei lo passa sempre e anche in altri esercizzi che ha svolo esegue il controllo dell'avvenuta inizializzazione delle variabili di istanza nel costruttore ![]() Sopratutto questa seconda cosa mi sconvolge un po'...una volta si incazzò in classe per questa cosa perchè diceva che il costruttore prima di creare un oggetto che dipende da una variabile di classe deve controllare che queste siano state correttamente inizializzate ![]() ![]() ![]() |
|
![]() |
![]() |
![]() |
#12 | |
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
Quote:
Ma poichè ti avevo detto di levare quel vettore che è orribile e viola il principio di incapsulamento, in quel caso non sarebbe servito a niente il controllo ![]()
__________________
![]() |
|
![]() |
![]() |
![]() |
#13 |
Bannato
Iscritto dal: Mar 2004
Città: Roma
Messaggi: 2682
|
Così dici che va meglio? L'equals che ho scritto è corretto?
Codice:
public class ArticoloInSupermercato{ // Array di stringhe di classe: rappresenta i reparti del supermercato private static String [] reparti = {"Ortofrutta", "macelleria", "pulizia casa", "benessere"}; private String nomeArticolo; // Nome dell'articolo in vendita, inizialmente a ull private double prezzoArticolo; // Prezzo dell'articolo in vendita private int quantitaArticolo; // Numero di oggetti in vendita per un certo articolo private int indiceReparto; // Indice di identificazione del reparto nell'array di classe reparti /** COSTRUTTORE: Inizializza tutte le variabili di istanza e crea un nuovo oggetto istanza della classe. @param nome di tipo String @param prezzo di tipo double @param quantita di tipo int @param indice di tipo int @return il riferimento ad un oggetto di tipo ArticoloInSupermercato */ public ArticoloInSupermercato(String nome, double prezzo, int quantita, int indice){ nomeArticolo = nome; // Metti il riferimento della stringa nome in nome_Articolo prezzoArticolo = prezzo; // Copia il valore double di prezzo in prezzo_Articolo quantitaArticolo = quantita; // Copia il valore int di quantita in quantita_Articolo indiceReparto = indice; // Copia il valore int di indice in indice_Reparto } /* METODI DI ACCESSO AI DATI: */ /** getNome: restituisce al chiamante il valore contenuto nel campo nome dell'oggetto ricevente @param void @return una stringa contenente il nome del prodotto */ public String getNome(){ return nomeArticolo; // Ritorna al chiamante il riferimento alla stringa contenente il nome dell'articolo } /** getPrezzo: restituisce al chiamante il valore contenuto nel campo prezzo dell'oggetto ricevente @param void @return una double contenente il prezzo del prodotto */ public double getPrezzo(){ return prezzoArticolo; // Ritorna al chiamante il riferimento alla stringa contenente il nome dell'articolo } /** getQuantita: restituisce al chiamante il valore contenuto nel campo prezzo quantita dell'articolo @param void @return un int contenente il numero di prodotti per uno specifico articolo */ public int getQuantita(){ return quantitaArticolo; } /** getRepartp: restituisce al chiamante il valore rappresentante l'indice nell'array dei reparti del supermercato @param void @return un int che rappresenta l'indice nell'array dei reparti del supermercato */ public int getReparto(){ return indiceReparto; } /* METODI DI UTILITA' */ /** METODO toSting: Restituisce al chiamante una stringa contenente i dati contenuti nelle variabili di istanza di un oggetto. @param void @return un oggetto di tipo String che contiene i dati delle variabili di istanza dell'oggetto ricevente sotto forma di stringa */ public String toString(){ String Risposta = "Il nome dell'articolo è: " + nomeArticolo + "Il prezzo è: " + prezzoArticolo + "Nel supermercato ci sono tot pezzi: " + quantitaArticolo + "L'articolo appartiene al reparto: " + reparti[indiceReparto]; return Risposta; } /** METODO EQUALS: ridefinisco il metodo equals per confrontare due oggetti istanza della classe ArticoliInSupermercato @parm prodotto di tipo ArticoloInSupermercato da confrontare con l'oggetto ricevente il messaggio @return esito di tipo boolean: TRUE se i due oggetti sono uguali, FALSE altrimenti. */ public boolean equals(ArticoloInSupermercato prodotto){ boolean esito = (nomeArticolo.equals(prodotto.nomeArticolo) && prezzoArticolo == prodotto.prezzoArticolo && quantitaArticolo == prodotto.quantitaArticolo && indiceReparto == prodotto.indiceReparto); return esito; } } Grazie Andrea Ultima modifica di D4rkAng3l : 30-01-2009 alle 18:11. |
![]() |
![]() |
![]() |
#14 | |
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
Quote:
![]() Il vettore di reparti va nella classe Supermercato, che sarebbe quella in cui metti il main e da cui istanzi i vari articoli passandogli solo il nome. Ogni articolo non deve avere alcuna conoscenza degli altri reparti dato che non è il suo compito ma quello del supermercato ![]() quanto al resto del codice puoi evitare di scrivere: Codice:
public String toString(){ String Risposta = "Il nome dell'articolo è: " + nomeArticolo + "Il prezzo è: " + prezzoArticolo + "Nel supermercato ci sono tot pezzi: " + quantitaArticolo + "L'articolo appartiene al reparto: " + reparti[indiceReparto]; return Risposta; } Codice:
return "Il nome dell'articolo è: " + nomeArticolo + "Il prezzo è: " + prezzoArticolo + "Nel supermercato ci sono tot pezzi: " + quantitaArticolo + "L'articolo appartiene al reparto: " + reparti[indiceReparto]; Quindi ricapitolando devi eliminare il vettore da questa classe e metterlo nella classe supermercato e poi passi all'articolo al posto dell'indice solo il nome come stringa. Ah... e segui la stessa convenzione con le minuscole / maiuscole... ortofrutta è scritto con la prima iniziale maiuscola mentre gli altri sono tutti in minuscolo....
__________________
![]() |
|
![]() |
![]() |
![]() |
#15 |
Bannato
Iscritto dal: Mar 2004
Città: Roma
Messaggi: 2682
|
mmm quindi praticamente mi stai dicendo che sarebbe meglio creare il vettore static e public nell'altra classe (dentro al main()) così nella classe ArticoliInSupermercato memorizzo solo l'indice relativo alla posizione del vettore e non tutto il vettore?
Grazie Andrea |
![]() |
![]() |
![]() |
#16 | |
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
Quote:
il vettore lo devi memorizzare nella classe Supermercato, quella dove c'è il main, ma l'indice non ti serve, l'articolo deve conoscere solo ed esclusivamente il nome del reparto, non deve avere coscienza degli altri reparti presenti nel supermercato perchè non è compito suo. E se ci pensi è perfettamente sensato... metti caso che hai svariate classi e in ogni classe ti porti l'elenco dei vettori, oppure memorizzi l'indice del reparto al loro interno.. Non appena devi cambiare questo elenco dei reparti ti ritrovi a dover aggiornare i vettori nelle varie classi oppure a correggere tutti gli indici che sono presenti in esse. Invece cosi' cambi semplicemente il vettore al'interno di supermercato e passi ad articolo solo il nome del reparto, e quindi continua a funzionare il tutto anche se aggiungi altri reparti nel vettore. ![]()
__________________
![]() |
|
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 21:16.