Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 16
  1. #1

    collezione Set di elementi

    Salve, volevo fare un programma con una semplice classe di questo tipo:

    codice:
    public class Utente {
        
        String Nome;
        String Cognome;
        Libro a;
        
        public void InserisciUtente(){
            Nome= JOptionPane.showInputDialog("Inserisci il nome utente");
            Cognome= JOptionPane.showInputDialog("Inserisci il cognome utente");
        }
        
    }

    Voglio creare più utenti che vengano poi inseriti dinamicamente durante l'esecuzione del programma e avevo pensato a una cosa del genere:

    codice:
    Object cercautente;
    Set utenti;
    utenti = new HashSet();
    
    Utente u= new Utente();
    u.InserisciUtente();
    utenti.add(u);
    Utente p = new Utente();
    Iterator iter=utenti.iterator();
    cercautente=iter.next();
    p=(Utente)cercautente;

    Non capisco se proprio è una cosa che con il Set non si può fare o cos'altro. Diciamo che non riesco ad accedere ai singoli campi di un Utente una volta inserito nella collezione. Grazie e spero possiate aiutarmi.
    Ultima modifica di LeleFT; 16-04-2015 a 14:54 Motivo: Aggiunti i tag CODE

  2. #2
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,317
    Alcune considerazioni:

    1) Da diversi anni (dall'uscita di Java 5) esistono i generics e le collezioni sono tipizzate. Di conseguenza, andrebbe definito il tipo della collezione. Nel tuo caso, quindi, per creare un HashSet di oggetti Utente, si usa questa sintassi:

    codice:
    HashSet<Utente> utenti = new HashSet<Utente>();

    Questo porta molti vantaggi: dai cast non più necessari ai benefici dovuti al controllo di correttezza in fase di compilazione, ecc.

    2) Se vuoi usare una tua classe all'interno di un HashSet, allora la tua classe deve necessariamente implementare il metodo hashCode() e lo deve implementare in modo corretto. Questo perchè l'indicizzazione della struttura dati avviene proprio mediante tale metodo. Se non lo fai, i risultati possono essere decisamente sballati.

    3) Una classe come Utente che incorpora al suo interno la logica di interazione con l'utente per l'acquisizione dei dati è il massimo dell'opposto della normale logica Object Oriented: in pratica stai stravolgendo tutti i principi della OOP. Sposta quel metodo da un'altra parte (tra parentesi, la nomenclatura Java prevede che i nomi dei metodi iniziano con la lettera minuscola; la lettera iniziale maiuscola è riservata alle classi/interfacce)

    4) Al di là del caso specifico (che non capisco perchè stai usando un iteratore...), quando si usa un iteratore la prima cosa che si deve fare, prima di richiamare il metodo next() è controllare che l'iteratore abbia "in canna" un elemento da leggere (ovvero, che non sia vuoto e che non sia arrivato alla fine), quindi:

    codice:
    Iterator<Utente> it = utenti.iterator();
    while( it.hasNext() ) {   // Scorro finchè ci sono elementi
       Utente utCercato = it.next();
    }

    Infine il tuo problema: cosa vuol dire che non riesci ad accedere ai campi? Ottieni qualche eccezione? Se sì, quale eccezione? Dovresti postarne lo stackTrace...


    Ciao.
    Ultima modifica di LeleFT; 16-04-2015 a 15:07
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  3. #3
    Grazie mille per le delucidazioni comunque sono alle prime armi è per quello che faccio errori anche banali
    Comunque si il codice non era completo era solo un pezzo, l'iteratore lo usavo poi per fare una ricerca di un utente sulla collezione. Ed è per questo che dico che non riesco ad accedere ai campi, nel senso che se voglio ricercare un utente con un determinato nome mi dava degli errori nello scrivere p.Nome.
    E si certamente ci andava un controllo come mi hai suggerito per l'iteratore.
    Ultima cosa, scusa l'ignoranza ma in che senso che stravolgo i principi di programmazione OOP? Cioè cosa porta di male il fatto che inserisco una iterazione con l'utente per acquisire dei dati all'interno di quella classe?
    Grazie ancora della pazienza.

  4. #4
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da campaenrico Visualizza il messaggio
    Ultima cosa, scusa l'ignoranza ma in che senso che stravolgo i principi di programmazione OOP? Cioè cosa porta di male il fatto che inserisco una iterazione con l'utente per acquisire dei dati all'interno di quella classe?
    Nella programmazione ad oggetti esiste un principio fondamentale che è quello della (alta) "coesione".
    Ovvero una classe è tanto più coesa quanto più è focalizzata su un solo obiettivo, ed è una buona cosa. Questo non vuol dire che la classe deve avere pochi campi/metodi ... vuol dire che tutti i campi/metodi dovrebbero essere in funzione di un solo, unico obiettivo.

    Se fai una classe Utente con campi nome, cognome, ecc.... allora l'obiettivo principale della classe dovrebbe essere quello di rappresentare un utente. Quindi può avere tutti i vari campi che modellano i dati dell'utente (preferibilmente marcati 'private', se non ci sono motivi ben particolari), poi tutti i metodi getter/setter per i campi, eventuali toString(), equals() ecc... standard, eventualmente compareTo di Comparable.

    Ma non dovrebbe fare altro! Se introduci un InserisciUtente() che richiede input fisico all'utente (in qualunque forma), stai gestendo un altro aspetto completamente diverso, quello della interazione con un utente "umano". E questo non va bene.
    Oltretutto hai usato qualcosa di molto specifico, la input dialog di Swing. E se io volessi usare la tua classe Utente in una applicazione puramente "console"? E se invece l'utente dovesse essere tirato "su" da database?
    La tua classe Utente diventa poco riutilizzabile e oltretutto sarebbe legata indissolubilmente a Swing.

    L'input da utente andrà fatto in un'altra classe, più focalizzata appunto alla interazione con un utente umano.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  5. #5
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,317
    Secondo i principi della OOP andrebbe separato ciò che è semplice "dato" da ciò che è "interazione con l'utente".
    Una classe che si chiama "Utente" dovrebbe solamente modellare i dati di una persona (nome, cognome, eventuali altri dati) e non dovrebbe occuparsi né di raccoglierli tali dati, né di sapere da dove arrivino (se da input dell'utente, da lettura di file, da comunicazione via rete, ecc).

    Una classe come "Utente", in Java si chiama "bean": è un contenitore di dati. Punto. Non fa alcun "lavoro" materiale (non ha logica applicativa al suo interno). Sarà un'altra parte del programma che si occuperà di raccogliere i dati e creare le istanze della classe Persona, passando loro i dati raccolti.

    Per quanto riguarda gli errori nello scrivere "p.Nome" è corretto che te li dia: Nome e Cognome (anche qui, minuscole e non maiuscole) sono campi "non pubblici" (ed è corretto che non lo siano... addirittura, io li definirei privati). Per potervi accedere devi fare in modo che la classe Persona fornisca dei metodi (cosiddetti, accessori: cioè di "accesso") per l'accesso.

    Io riscriverei la classe Utente in questo modo:

    codice:
    public class Utente {
       private String nome;
       private String cognome;
       private Libro libro;   // Non sono sicuro che sia esattamente ciò che vuoi, ma al momento va bene così
    
       // Metodi setter: servono a impostare i valori
       public void setNome(String nome) {
          this.nome = nome;
       }
    
       public void setCognome(String cognome) {
          this.cognome = cognome;
       }
    
       public void setLibro(Libro libro) {
          this.libro = libro;
       }
    
       // Metodi getter: servono a "leggere" i valori del bean
       public String getNome() {
          return nome;
       }
    
       public String getCognome() {
          return cognome;
       }
    
       public Libro getLibro() {
          return libro;
       }
    
       // equals() e hashCode(): vanno sempre in coppia!
       @Override
       public boolean equals(Object obj) {
          if (!(object instanceof Persona)) {
             return false;
          }
    
          Utente other = (Utente) obj
          if ((this.nome == null && other.nome != null) || (this.nome != null && !this.nome.equals(other.nome))) {
             return false;
          }
           if ((this.cognome == null && other.cognome != null) ||  (this.cognome != null && !this.cognome.equals(other.cognome))) {
             return false;
          }
          return true;
       }
    
       @Override
       public int hashCode() {
          int hash = 0;
          hash += (nome != null ? home.hashCode() : 0);
          hash += (cognome != null ? cognome.hashCode() : 0);
          return hash;
       }
    }

    Sposterei la richiesta del nome e del cognome in una funzione del programma principale... dopo aver ottenuto nome e cognome, istanzi l'oggetto Utente e gli passi i valori usando i metodi setter appositi. Dopo di ciò, butti l'oggetto nel HashSet


    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  6. #6
    Grazie ancora, e per quanto riguarda l'input da Swing un modo alternativo può essere di questo tipo:
    Scanner s= new Scanner(System.in);
    int risp;
    risp= s.nextInt();
    Se per esempio voglio un intero ovviamente.

  7. #7
    Il codice sembra funzionare ora ma mi da un problema:
    HashSet<Utente> utenti = new HashSet<>();
    Iterator<Utente> it1 = utenti.iterator();
    Utente cercautente=new Utente();
    if(it1.hasNext())
    cercautente=it1.next();

    eseguendo cercautente.getnome mi restituisce sempre un valore null. Cos'è che sbaglio o in quale altro modo posso accedere a uno dei campi degli oggetti della collezione?

  8. #8
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da campaenrico Visualizza il messaggio
    codice:
    HashSet<Utente> utenti = new HashSet<>();
    Iterator<Utente> it1 = utenti.iterator();
    Utente cercautente=new Utente();
           if(it1.hasNext())
                 cercautente=it1.next();
    eseguendo cercautente.getnome mi restituisce sempre un valore null
    Il contesto purtroppo non è molto chiaro .... se hai appena istanziato un nuovo HashSet, esso è vuoto, quindi cosa ti aspetti dalla iterazione?

    E poi visto che usi i generics (e quindi almeno Java 5), sfrutta anche il "for-each":

    codice:
    for (Utente utente : utenti) {
        // usa utente i-esimo
    }

    Non serve infatti istanziare un oggetto Utente ... è la iterazione che ti fornisce quelli presenti nel HashSet.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  9. #9
    [QUOTE=andbin;25303782]Il contesto purtroppo non è molto chiaro .... se hai appena istanziato un nuovo HashSet, esso è vuoto, quindi cosa ti aspetti dalla iterazione?

    si scusami li inserivo così come avevo scritto nel primo codice
    Utente u= new Utente();
    u.InserisciUtente();
    utenti.add(u);


    E il for che mi hai scritto secondo quale condizione continua gira tutti gli utenti in qualsiasi caso?

  10. #10
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da campaenrico Visualizza il messaggio
    E il for che mi hai scritto secondo quale condizione continua gira tutti gli utenti in qualsiasi caso?
    Il for-each itera tutti gli elementi nell'oggetto Iterable (nel tuo caso il HashSet). Sotto, di nascosto, usa nient'altro che un Iterator replicando di fatto lo stesso codice while, test hasNext ... next che dovresti scrivere tu a mano. E il for-each quindi è più breve e anche più leggibile.

    E siccome è HashSet, ricorda che l'ordine di iterazione non è prevedibile e può anche cambiare man mano che il HashSet si espande.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.