Aiutino per richiamare metodi di altre classi?

di il
40 risposte

40 Risposte - Pagina 3

  • Re: Aiutino per richiamare metodi di altre classi?

    Mi intrometto io anche se Ansharja ti ha sicuramente supportato egregiamente (non ho letto tutta la discussione).

    xXNicolaXx ha scritto:


    Ora, quello che voglio capire...nella classe bicicletta, non ci sono oggetti, giusto? L'oggetto è quella "cosa" che viene dichiarata con nomeclasse nomeoggetto = new nomecostruttore(parametri), giusto? O forse tutti gli attributi e i metodi della classe Bicycle rappresentano un oggetto però in senso astratto, nel senso che se paragonato alla realtà, la bicicletta è un oggetto e ha quelli stati e funzioni?
    Nel nostro caso abbiamo creato l'oggetto "p", che è di tipo passeggero(quindi di tipo passeggero significa che richiama metodi o attributi della classe passeggero? giusto per capire se ho capito).
    Un oggetto prende vita quando da qualche parte viene fatto un new Tipo() (con o senza argomenti, non importa ora). Un oggetto deve essere allocato sul heap di memoria in modo che occupi quel tot di memoria contigua sufficiente a contenere tutti i campi di istanza più "qualcosina" che serve in modo intrinseco alla gestione degli oggetti.

    La classe Bicycle ha 3 campi int, quindi quando farai new Bicycle(), sul heap di memoria di Java verrà allocato uno spazio di almeno 3x4 byte (nota: 1 int = 32 bit = 4 byte) più qualcosa in più che serve fisso intrinsecamente alla JVM per la gestione dell'oggetto. E se la costruzione ha successo viene fornito il reference all'oggetto che è quello che puoi assegnare ad una variabile come in:

    Bicycle b = new Bicycle();
  • Re: Aiutino per richiamare metodi di altre classi?

    andbin ha scritto:


    Mi intrometto io anche se Ansharja ti ha sicuramente supportato egregiamente (non ho letto tutta la discussione).

    xXNicolaXx ha scritto:


    Ora, quello che voglio capire...nella classe bicicletta, non ci sono oggetti, giusto? L'oggetto è quella "cosa" che viene dichiarata con nomeclasse nomeoggetto = new nomecostruttore(parametri), giusto? O forse tutti gli attributi e i metodi della classe Bicycle rappresentano un oggetto però in senso astratto, nel senso che se paragonato alla realtà, la bicicletta è un oggetto e ha quelli stati e funzioni?
    Nel nostro caso abbiamo creato l'oggetto "p", che è di tipo passeggero(quindi di tipo passeggero significa che richiama metodi o attributi della classe passeggero? giusto per capire se ho capito).
    Un oggetto prende vita quando da qualche parte viene fatto un new Tipo() (con o senza argomenti, non importa ora). Un oggetto deve essere allocato sul heap di memoria in modo che occupi quel tot di memoria contigua sufficiente a contenere tutti i campi di istanza più "qualcosina" che serve in modo intrinseco alla gestione degli oggetti.

    La classe Bicycle ha 3 campi int, quindi quando farai new Bicycle(), sul heap di memoria di Java verrà allocato uno spazio di almeno 3x4 byte (nota: 1 int = 32 bit = 4 byte) più qualcosa in più che serve fisso intrinsecamente alla JVM per la gestione dell'oggetto. E se la costruzione ha successo viene fornito il reference all'oggetto che è quello che puoi assegnare ad una variabile come in:

    Bicycle b = new Bicycle();
    Ah capito, ora mi è molto più chiaro. Grazie dell'ottima spiegazione(non che Ansharja non mi abbia spiegato bene, anzi, è solo grazie a lui se fino ad ora ho fatto e capito qualcosa).
  • Re: Aiutino per richiamare metodi di altre classi?

    Eccoci qua, riprendo da dove ero arrivato

    xXNicolaXx ha scritto:


    Incredibile!! [...]
    
    package aereoporto;
    import java.util.ArrayList;
    import java.util.Scanner;
    public class Registrazione {
        Scanner tastiera = new Scanner(System.in);
        private String scelta;
        Passeggero[] passeggeri = new Passeggero[10];      
        [...]	
        public void inserimentoPasseggero() {
           for(int i=0; i<passeggeri.length; i++){
            System.out.println("Benvenuto! Inserisca il suo nome : ");
            String nome = tastiera.nextLine();
            System.out.println("Inserisca il suo cognome : ");
            String cognome = tastiera.nextLine();
            passeggeri[i] = new Passeggero(nome, cognome);
            System.out.println("Registrazione avvenuta con successo!");
            Passeggero p = new Passeggero(nome, cognome);       
            gestisciOperazioni();
           }
        }    
    	[...]
    }
    
    Spero sia giusto [...]
    Edit: no..no..è sbagliato.. [...]
    Ok, ho tenuto solo i passaggi fondamentali.
    Prima cosa: le variabili di istanza di Registrazione. Ho già visto che andbin ti ha spiegato che i campi occupano spazio sul heap di memoria. Per ora hai pochissime variabili, e occupano pochissimo spazio, quindi ce ne vuole (ma taaaaaanto ce ne vuole) prima che tu lo esaurisca, tranquillo.
    Però devi capire cosa ha senso tenere come campo di istanza e cosa invece non ne ha, per ora è solo una questione di pulizia e di ordine, ma aiuta anche chi legge.
    Il vettore passeggeri ha senso che sia un campo di istanza, perché tutti i metodi all'interno di Registrazione devono far riferimento a quel particolare vettore che tu stai popolando (almeno per come stanno ora le cose). Quindi non avrebbe senso che tu ne creassi uno nuovo ogni volta.
    La stringa scelta invece non ha senso di esistere come campo di istanza. E' una variabile comoda all'interno del metodo gestisciOperazioni(), ma altrove non te ne fai nulla. Non è una proprietà di Registrazione, quindi creala solo all'interno di gestisciOperazioni(): anche se la crei più volte non c'è il minimo problema, e quando esci dal metodo sarà cancellata, non stai "sprecando" nulla.

    Attento: non ti dico questo perché tu diventi un fanatico della gestione della memoria, nulla del genere, e ovviamente tenere un campo in più o in meno (ma anche parecchie decine di campi) alla jvm cambia relativamente poco (o nulla).
    Voglio solo iniziare a farti pensare a cosa deve/conviene che sia un campo dell'oggetto e cosa no.
    Ora potresti dire: ma allora perché salvare lo Scanner come variabile di istanza? Una Registrazione non ha come proprietà lo scanner, a me interessa solo che abbia il vettore dei passeggeri per ora.

    E' vero, ma dicevo nei primissimi messaggi (è una cosa che ho imparato da andbin tra l'altro ) che ti conviene creare ed utilizzare un solo Scanner all'interno della tua classe. Uno scanner è un oggetto un po' più delicato, non ha molto senso crearne uno nuovo tutte le volte, per ora segui questo consiglio.

    Scusa la parentesi noiosa, ma almeno una volta pensavo valesse la pena di farlo, al massimo in seguito ti farò notare cosa potresti togliere, senza troppe chiacchiere .
    Ora il punto cruciale del programma, che è il motivo per cui non funziona: non guardo neanche come l'hai corretto per ora, devi capire perché questo non va bene.

    In inserimentoPasseggero() hai creato un ciclo che non deve assolutamente esserci (a meno che non lo volessi fare tu, vedi dopo). Il metodo è fatto per creare ed aggiungere al tuo vettore un unico passeggero con i dati letti dall'utente, né più né meno.
    Il ciclo che hai scritto tu invece ti stampa quei messaggi a video, legge nome e cognome, aggiunge il passeggero creato al posto i del vettore, poi ne crea un altro a caso (non te ne fai più nulla di quel p, non lo stai usando!).
    Ma la cosa peggiore è che come ultima istruzione del ciclo richiami il metodo gestisciOperazioni() (che non ha bisogno di essere chiamato se non nel main() la prima volta, te lo ridico dopo).

    Stai facendo quindi una ricorsione: quando torni dentro a gestisciOperazioni() il programma "sa" di essere ancora dentro al ciclo in inserimentoPasseggero(), con i=0, quindi anche se tu scegliessi di uscire dal programma, ad esempio digitando 4, il flusso uscirebbe dal do-while (perché la condizione non è più rispettata), ma poi ritornerebbe subito al termine della riga gestisciOperazioni() dentro al ciclo, incrementando i (che diventa pari a 1) e poi ricominciando un altro giro del for.
    Se addirittura invece che scrivere 4 nel passo precedente avessi scritto 1, saresti entrato in un nuovo ciclo ancora, e ne avresti due di "aperti".
    Capirai che questo è un casino terribile, e sono sicuro che non avevi intenzione di farlo.

    Tu non hai bisogno di chiamare gestisciOperazioni() all'interno di inserimentoPasseggero(): quando il programma è nello switch la prima volta che entri nel menù e tu inserisci "1", infatti, lui richiama il metodo inserimentoPasseggero().
    Ma quando il metodo termina (immagina per ora che non ci sia quel loop sbagliato) il programma riparte da dove era rimasto prima della chiamata, cioè ora sei a quel "break" all'interno dello switch.
    Quell'istruzione termina lo switch e il flusso arriva al controllo della condizione del while, scelta ora vale "1", quindi rientri nel do-while per un altro giro (e così fino a quando scelta rimarrà "1", "2" o "3").

    In pratica il programma "si ricorda" dove era rimasto prima di una chiamata, non lo devi riportare tu su gestisciOperazioni(), altrimenti crei un loop infinito (te l'ho spiegato terra-terra senza nominare gli stack e altre cose che conosco poco).

    Quindi ora rimuovi quella istruzione gestisciOperazioni() al termine del ciclo. Problema risolto ? No, non ancora!
    Senza quell'istruzione quando il ciclo arriva al termine, ricominci subito un altro giro (ne farai dieci in tutto, vista la condizione). Ad ogni giro riempi la cella successiva dell'array fino alla fine.

    Ma il metodo deve creare un solo Passeggero, non tutti in una volta! Se invece la tua intenzione era di aggiungere tutti i passeggeri in una volta, parte di quello che ho detto sarà superfluo, me ne scuso
    Però in quel caso sarebbe meglio chiamare il metodo assegnaTuttiIPasseggeri, o una cosa del genere, perché il nome è fuorviante e anche il messaggio nel menù.

    Ricorda che usare un vettore non vuol dire automaticamente dover usare un ciclo! Il classico (for int i=0;i<passeggeri.length;i++) è solo un modo tradizionale di ciclare un intero vettore per fare un'operazione su tutti i suoi elementi.
    Ad esempio per la stampa, il ciclo è quello che ti serve. Ma non vuol dire che sia sempre la cosa da fare...
    
    int[] vettore = new int[100];
    vettore[3] = 2;
    vettore[6] = 4;
    vettore[9] = 6;
    vettore[12] = 8;
    
    Io posso benissimo voler assegnare solo alcuni valori al vettore, in questo caso non uso il ciclo. Ma se volessi fare un ciclo con un'unica istruzione, mi sapresti dire come faresti (tanto per farti un esempio in cui si spezza quella dichiarazione del for che ho scritto prima, stavolta i++ non è la migliore scelta, e non solo...)?

    Scusami ancora se quello che ho scritto lo sapevi già, ora sarò più sintetico .

    xXNicolaXx ha scritto:


    Perdona il triplo post..ma finalmente funziona, tranne per una cosa... [...]
    
        public void inserimentoPasseggero() {
            
           for(int i=0; i<passeggeri.length; i++){
               cont++;
            System.out.println("Benvenuto! Inserisca il suo nome : ");
            String nome = tastiera.nextLine();
            System.out.println("Inserisca il suo cognome : ");
            String cognome = tastiera.nextLine();
            passeggeri[cont] = new Passeggero(nome, cognome);
            System.out.println("Registrazione avvenuta con successo!");
             Passeggero p = new Passeggero(nome, cognome);
           
            gestisciOperazioni();
           }
        }
    	
    [...]
    Il fatto che qui mantieni il ciclo anche se assegni il Passeggero alla posizione fornita da cont mi fa pensare che in effetti quella cosa sul ciclo non ti fosse chiara. Per l'uso di cont lo dici già tu in seguito, andiamo avanti.

    xXNicolaXx ha scritto:


    [...]
    
    Class Bicycle {
    
    int cadence = 0;
    int speed = 0;
    int gear = 1;
    
    void changeCadence(int newValue) {
    cadence = newvalue;
    }
    void changeGear(int newValue) {
    gear = newValue;
    }
    void speedUp(int increment) {
    speed = speed+increment;
    }
    void applyBrakes(int decrement) {
    speed = speed - decrement;
    }
    void printStates() {
    System.out.println("cadence:"+cadence+"speed:"+speed+"gear:"+gear);
    }
    
    [...]
    Per quanto riguarda la classe Bicycle solo poche cose: speedUp() e applyBrakes() sono dei metodi un po' più elaborati per modificare speed, ma oltre a quello la classe non è proprio standard.
    Intanto i campi non sono privati, sarebbe meglio se lo fossero. Diverso sarebbe se la classe dovesse essere estesa, nel qual caso i campi devono necessariamente non essere private (i membri privati non vengono ereditati).
    Poi i metodi changeCadence() e changeGear() non sono altro che dei setter e mancano i metodi getter.
    Infine printStates() non sostituisce il toString(), quel metodo effettua già la stampa, non restituisce la stringa che rappresenta l'oggetto!
    Lo puoi fare, per carità, ma i vantaggi del toString() sono tanti, e ne hai visto solo una parte, quindi perché avere un metodo che lo "scimmiotta" quando puoi ridefinire quello ?
    Insisto un po' su questo perché è lo schema che si cerca di "inculcare" a chi inizia a programmare: campi privati e metodi getter/setter. Inoltre nella stessa descrizione del metodo toString() di Object, nel link alla documentazione ufficiale che ti avevo fornito in precedenza, è specificato che si raccomanda alle sottoclassi di ridefinire questo metodo. Questo schema è riconosciuto da tutti, se tu sei in una classe esterna e vedi scritto setSpeed(int value), sai già cosa dovrebbe succedere, se il metodo ha un nome diverso non ne sei sicuro, puoi solo fare ipotesi.

    Ma sono convenzioni, non è scritto in nessun testo sacro, almeno credo .

    xXNicolaXx ha scritto:


    Ora, quello che voglio capire...nella classe bicicletta, non ci sono oggetti, giusto? L'oggetto è quella "cosa" che viene dichiarata con nomeclasse nomeoggetto = new nomecostruttore(parametri), giusto? O forse tutti gli attributi e i metodi della classe Bicycle rappresentano un oggetto però in senso astratto, nel senso che se paragonato alla realtà, la bicicletta è un oggetto e ha quelli stati e funzioni?
    Nel nostro caso abbiamo creato l'oggetto "p", che è di tipo passeggero(quindi di tipo passeggero significa che richiama metodi o attributi della classe passeggero? giusto per capire se ho capito).
    A questo ha già risposto andbin. E' stato molto specifico, ma mi ricordo che in un altro post proprio lui aveva usato un esempio più figurato che mi era piaciuto molto, spero non gli dispiaccia se lo riprendo
    In quell'esempio si paragonava i campi/metodi di una classe come a delle formine che usano i bambini nella sabbia. Quello è lo "scheletro" di come sarà il tuo oggetto una volta creato, quando poi tu scrivi new Nome_Classe() è come se stessi prendendo la sabbia, riempiendo la formina e girandola sulla spiaggia per costruire l'oggetto vero e proprio!
    L'oggetto "p" a cui facevo riferimento più in alto è di tipo Passeggero, quindi come hai scritto avrà ( = potrà richiamare su di sè) tutti i metodi della classe Passeggero, e avrà all'interno tutti i campi/attributi (sono più o meno sinonimi in questo contesto) che hai dichiarato sempre in Passeggero.
    Il fatto è che p, che hai ancora nel metodo inserimentoPasseggero, continua a essere inutilizzato nel codice. Attento che creare due oggetti Passeggero, anche se con lo stesso nome e cognome, crea due oggetti diversi!

    Tu sopra crei un Passeggero che viene assegnato in posizione[cont] all'array passeggeri. Sotto ne crei un altro, p, con lo stesso nome e lo stesso cognome e poi lo lasci lì.
    Per tornare all'esempio della spiaggia è come se tu riempissi di nuovo la tua formina o il tuo secchiello di sabbia, e poi lo rovesciassi nel mare (non lo recuperi più in alcun modo, togli quella riga )...

    xXNicolaXx ha scritto:


    Adesso, proprio mentre scrivevo il messaggio, ho risolto involontariamente il problema che i numeri venivano incrementati di 2 alla volta.
    Considera il mio ultimo codice funzionante, che però aveva il problema dei numeri doppi appunto. Ho semplicemente tolto
    
     Passeggero p = new Passeggero(nome, cognome);
     
    che si trovava sotto
    
    System.out.println("Registrazione avvenuta con successo!");
    
    e adesso appunto funziona..però vorrei capire perchè..Come mai creava il problema del numero doppio, se io passavo solo le stringhe nome e cognome nel costruttore? Il numero non lo richiamavo, vero?
    ps. il contatore l'ho spostato dopo l'inserimento perchè altrimenti creava il problema che dicevi tu
    Eliminare quella riga non cambia niente nel tuo programma, cioè hai solo rimosso (giustamente!!) una riga inutile dal codice, ma non stai modificando in nessun modo l'indice i e il contatore.
    Devi ancora sistemare quel metodo
  • Re: Aiutino per richiamare metodi di altre classi?

    Quindi, adesso che però ho tolto quella parte che dicevi anche tu di togliere, funziona correttamente. Cioè, se inserisco il primo paaseggero, lo inserisce nella posizione 0, se inserisco il secondo, lo inserisce nella posizione 1 e così via. Poi quando scelgo l opzione 2 del menù, lui mi stampa i nomi inseriti con il loro numero assegnato correttamente. Non ho ben capito cos'è che non va.
    Non so se tu hai avuto modo di compilarlo, nel caso se hai tempo fallo così mi dici proprio qual'è il punto che non va bene(se me l hai già chiesto chiedo scusa, ma non l ho capito, perché effettivamente a me sembra funzionare tutto correttamente)
  • Re: Aiutino per richiamare metodi di altre classi?

    xXNicolaXx ha scritto:


    Quindi, adesso che però ho tolto quella parte che dicevi anche tu di togliere, funziona correttamente. Cioè, se inserisco il primo paaseggero, lo inserisce nella posizione 0, se inserisco il secondo, lo inserisce nella posizione 1 e così via. Poi quando scelgo l opzione 2 del menù, lui mi stampa i nomi inseriti con il loro numero assegnato correttamente. Non ho ben capito cos'è che non va.
    Non so se tu hai avuto modo di compilarlo, nel caso se hai tempo fallo così mi dici proprio qual'è il punto che non va bene(se me l hai già chiesto chiedo scusa, ma non l ho capito, perché effettivamente a me sembra funzionare tutto correttamente)
    Non è molto chiaro questo messaggio... Hai tolto il ciclo da inserimentoPasseggero()? E il richiamo a gestisciOperazioni()?
    Se hai modificato correttamente la parte sul contatore non ci sono molte cause di errore, posta il codice, non farmi indovinare
  • Re: Aiutino per richiamare metodi di altre classi?

    Ansharja ha scritto:



    Non è molto chiaro questo messaggio... Hai tolto il ciclo da inserimentoPasseggero()? E il richiamo a gestisciOperazioni()?
    Se hai modificato correttamente la parte sul contatore non ci sono molte cause di errore, posta il codice, non farmi indovinare
    Si scusa hai ragione..quando ho riletto la seconda volta il tuo messaggio mi era sfuggita questa parte. Comunque forse adesso mi è un po' più chiaro un po' tutto il programma. Vorrei solo ancora capire una cosa:
    quando scrivo
    passeggeri[cont] = new Passeggero(nome, cognome);
    "Passeggero" si riferisce alla classe o al costruttore? In questo caso non mi serve creare un oggetto della classe passeggero(come prima, con tipo Passeggero p = new Passeggero ) perchè il vettore "passeggeri" appartiene già alla classe Passeggero?
    Ho tolto il ciclo che in effetti non serviva a niente, dato che la "i" non la usavo da nessuna parte..e ho tolto anche il richiamo a "gestisciOperazioni()".
    Ora ti riposto il codice corretto(spero )
    Classe aereoporto:
    
    package aereoporto;
    
    import java.util.Scanner;
    
    public class Registrazione {
    
        Scanner tastiera = new Scanner(System.in);
        private String scelta;
        private int cont = 0;
        Passeggero[] passeggeri = new Passeggero[10];
       
        
        public void gestisciOperazioni(){
            
           do{ System.out.println("Seleziona una voce dal menù: ");
            System.out.println("1 Registra nuovo passeggero");
            System.out.println("2 Stampa lista passeggeri");
            System.out.println("3 Modifica dati passeggero");
            scelta = tastiera.nextLine();
            switch(scelta){
                case "1":
                inserimentoPasseggero();
                break;
                case "2":
                stampaPasseggeri();
                break;
                case "3":
                modificaPasseggero();
                break;
                default:
                System.out.println("Scelta non valida. Riprovare.");
                
              }}while(scelta.equals("1") || scelta.equals("2") || scelta.equals("3"));
            
        }
        
        public void inserimentoPasseggero() {
           
           
           
            System.out.println("Benvenuto! Inserisca il suo nome : ");
            String nome = tastiera.nextLine();
            System.out.println("Inserisca il suo cognome : ");
            String cognome = tastiera.nextLine();
            passeggeri[cont] = new Passeggero(nome, cognome);
            System.out.println("Registrazione avvenuta con successo!");
            cont++;
           
          
           
        }
        public void stampaPasseggeri(){
            for (int i=0; i<passeggeri.length; i++){
            System.out.println(passeggeri[i]);
            }
            
            gestisciOperazioni();
        }
       
        public void modificaPasseggero(){
        }
       
    }     
    
    Classe Passeggero:
    package aereoporto;
    
    public class Passeggero {
    
        private String nome;
        private String cognome;
        private int numero;
        private static int numeroPasseggeri = 0;
        
    
        public Passeggero(String nome, String cognome) {
            this.nome = nome;
            this.cognome = cognome;
            this.numero = numeroPasseggeri;
            numeroPasseggeri++;
    
        }
    
        Passeggero() {
    
        }
    
        public String getNome() {
            return nome;
        }
    
        public String getCognome() {
            return cognome;
        }
    
        public int getNumero() {
            return numero;
        }
    
        @Override
        public String toString() {
            return "Passeggero : " + nome + " " + cognome + " Numero : " + numero;
        }
    
    }
    
    Ps. Ma quindi la stampa del vettore devo lasciarla con il metodo che ho fatto StampaPasseggeri() o dovrei usare il toString?
    Non mi ricordo se prima mi avevi chiesto perchè si chiamava "StampaPasseggeri" invece che "StampaPasseggero". Beh semplicemente perchè non voglio stampare un singolo passeggero ma tutti quelli che si sono registrati fino a quel momento.
    Forse non me l'hai mai chiesta una cosa del genere e ti riferivi ad altro, ma ora non ricordo e non ho molto tempo per ricontrollare il tutto
  • Re: Aiutino per richiamare metodi di altre classi?

    xXNicolaXx ha scritto:


    Vorrei solo ancora capire una cosa:
    quando scrivo
    passeggeri[cont] = new Passeggero(nome, cognome);
    "Passeggero" si riferisce alla classe o al costruttore?
    Un po' tutte e due Con quella istruzione stai richiamando il costruttore della classe Passeggero, ma il costruttore è intrinsecamente legato al nome della classe, non può essere definito in altro modo.

    xXNicolaXx ha scritto:


    In questo caso non mi serve creare un oggetto della classe passeggero(come prima, con tipo Passeggero p = new Passeggero ) perchè il vettore "passeggeri" appartiene già alla classe Passeggero?
    Alt, questa cosa non ti è ancora chiara. Tu lo stai creando l'oggetto con quella istruzione, solo che non lo stai assegnando a una variabile. Queste tre righe di codice fanno cose molto simili, ma con risultati diversi :
    
    new Passeggero();
    Passeggero p = new Passeggero();
    passeggeri[indice] = new Passeggero();
    
    Immagina che il costruttore non prenda parametri in ingresso, per ora non ha importanza.
    La prima riga crea un nuovo Passeggero, cioè il costruttore viene richiamato e restituisce il riferimento al nuovo oggetto Passeggero, solo che tu non lo assegni ad alcuna variabile, non lo aggiungi a nessun vettore, non lo usi.
    Ma questo non significa che tu non l'abbia creato (come dicevo prima, è come se lo stessi buttando nel mare)!

    La seconda riga invece assegna il riferimento del Passeggero appena creato a p. Con quel riferimento puoi ora fare qualsiasi cosa, ad esempio assegnarlo al tuo vettore in una qualche posizione. Per esempio così :
    
    Passeggero p = new Passeggero();
    passeggeri[indice] = p;
    
    Ti deve essere chiaro che queste due righe fanno praticamente ciò che fa la terza riga del codice sopra, solo con un passaggio in più. Nella terza riga di sopra il riferimento al Passeggero creato viene assegnato direttamente alla posizione "indice" del vettore.
    Con il codice subito sopra invece il riferimento al passeggero creato viene prima assegnato a p, e in seguito assegnato anche all'interno del vettore. Tipicamente ti basta la singola riga di codice, se vuoi fare solo l'assegnamento.
    Memorizzare anche in p il nuovo passeggero può essere utile se nel seguito del codice lo devi riutilizzare, ad esempio per stamparlo a video, senza doverlo andare a "ripescare" dal vettore dove l'hai appena inserito.

    Il vettore passeggeri conterrà all'interno oggetti di tipo di Passeggero, ma abbiamo già detto che non "appartiene" alla classe Passeggero, è solo un contenitore. Quando tu scrivi :
    
    passeggeri = new Passeggero[10];
    
    Stai solo "preparando lo spazio" per il vettore, informando il programma circa il tipo di oggetti che saranno contenuti dentro a passeggeri (quindi non potrai inserire dentro stringhe o altro).
    Ma se tu potessi "guardare" dentro a passeggeri subito dopo la sua creazione, "troveresti all'interno" questo:
    
    {null, null, null, null, null, null, null, null, null, null}
    
    Il fatto di creare il vettore non lo riempie di oggetti, all'interno del vettore ogni cella "punta" a null, tu hai solo "preparato" il contenitore a ricevere gli oggetti, ma li devi ancora aggiungere (creandoli!).
    Questo in genere quando crei un vettore di oggetti, se istanzi un vettore di tipo primitivo, come int, ogni cella dell'array conterrà 0: questo perché un tipo primitivo, come dicevamo, non può essere null.
    Quindi spero sia chiaro che tu, con la riga che hai postato, lo stai creando l'oggetto con la chiamata a "new Passeggero(/*...*/)", e lo stai passando alla cella del vettore.

    xXNicolaXx ha scritto:


    Ora ti riposto il codice corretto(spero ) [...]
    Ok hai sistemato quello che dicevo. Attento che anche in stampaPasseggeri() devi togliere la chiamata a gestisciOperazioni(), altrimenti ritorni a quello che dicevo due messaggi fa (poi potresti ancora rimuovere il costruttore vuoto di Passeggero e togliere scelta come campo di istanza di Registrazione).

    xXNicolaXx ha scritto:


    Ps. Ma quindi la stampa del vettore devo lasciarla con il metodo che ho fatto StampaPasseggeri() o dovrei usare il toString?
    Non mi ricordo se prima mi avevi chiesto perchè si chiamava "StampaPasseggeri" invece che "StampaPasseggero". Beh semplicemente perchè non voglio stampare un singolo passeggero ma tutti quelli che si sono registrati fino a quel momento.
    Forse non me l'hai mai chiesta una cosa del genere e ti riferivi ad altro, ma ora non ricordo e non ho molto tempo per ricontrollare il tutto.
    Il metodo stampaPasseggeri va benissimo per stampare il vettore.Ma tu lo stai usando il toString()! All'interno del ciclo, quando fai la stampa del singolo passeggero, lui va a prendersi il toString() che restituisce ogni Passeggero!
    In questa classe va benissimo il metodo e non è sbagliato che si chiami in quel modo. Tu ti riferisci al fatto che avevo criticato avere un metodo stampaPasseggeri() all'interno della classe Passeggero...

    E' sempre il discorso delle carte: tu non puoi chiedere al singolo Passeggero di stampare tutti gli altri passeggeri, ma nella classe che li gestisce tutti è corretto usare un metodo stampaPasseggeri() (ma la critica era solo al nome del metodo, non è che da dentro la classe Passeggero prima li stessi stampando tutti, solo che uno poteva crederlo).

    Ps: Il concetto di reference (quello che io chiamavo riferimento, non so neanche se sia la parola più indicata) e di oggetto non è proprio la stessa cosa. Dovresti cercare online delle buone spiegazioni che ti indichino la differenza, io non sono la persona più adatta.
    Nel mio messaggio ho cercato di spiegare le cose nel modo che a me sembrava più facile da comprendere, ma a livello formale potrei essere stato un po' impreciso...
  • Re: Aiutino per richiamare metodi di altre classi?

    Un po' tutte e due Con quella istruzione stai richiamando il costruttore della classe Passeggero, ma il costruttore è intrinsecamente legato al nome della classe, non può essere definito in altro modo.
    Bene, finalmente mi è chiaro
    Ti deve essere chiaro che queste due righe fanno praticamente ciò che fa la terza riga del codice sopra, solo con un passaggio in più. Nella terza riga di sopra il riferimento al Passeggero creato viene assegnato direttamente alla posizione "indice" del vettore.
    Con il codice subito sopra invece il riferimento al passeggero creato viene prima assegnato a p, e in seguito assegnato anche all'interno del vettore. Tipicamente ti basta la singola riga di codice, se vuoi fare solo l'assegnamento.
    Anche questo penso di averlo finalmente capito
    (poi potresti ancora rimuovere il costruttore vuoto di Passeggero e togliere scelta come campo di istanza di Registrazione).
    Hahah hai ragione, sai che mentre scrivevo questo messaggio ti stavo per dire "ma dov'è il costruttore vuoto?". Mi ero proprio dimenticato di averlo messo, e infatti non lo vedevo nemmeno più
    Scelta avevo provato a metterla dentro il metodo ma mi dava errore...ho capito ora che bastava togliere il private, perchè in effetti non ha senso(infatti mi dava come errore "illegal start of expression". L'ho messo prima del do...come mai se la metto dentro il do, prima dell'inserimento da tastiera, mi da errore sulla riga del while sottolineando "scelta" dove c'è scritto scelta.equals("1") ecc? Come se non trova scelta...
    Il metodo stampaPasseggeri va benissimo per stampare il vettore.Ma tu lo stai usando il toString()! All'interno del ciclo, quando fai la stampa del singolo passeggero, lui va a prendersi il toString() che restituisce ogni Passeggero!
    Questo invece non l'ho capito..come fa a prendersi il toString() da solo? Prima non l'avevo richiamato scrivendo
    System.out.println(p.toString()); //oppure
    System.out.println(p);
    
    Adesso ho provato a toglierlo e in effetti non funziona..però vorrei capire il modo in cui lo richiama. Inoltre questo toString, invece che mettendo la stampa di "nome" + "cognome" ecc..si poteva fare facendo stampare il vettore? Cioè, mettendo return passeggeri[cont]?
    Poi non ho capito ancora una cosa..nel costruttore di passeggero..se abbiamo detto che numero è = a numeroPasseggeri e viene incrementato numeroPasseggeri..perchè dal toString() se invece che far stampare il numero faccio stampare numeroPasseggeri, mi stampa tutti i numeri uguali?
    Cioè, se metto 3 passeggeri stampa a ogni passeggero il numero 3.
    Mentre se lascio la variabile numero allora stampa 0,1,2 ovvero correttamente.
  • Re: Aiutino per richiamare metodi di altre classi?

    xXNicolaXx ha scritto:


    System.out.println(p.toString()); //oppure
    System.out.println(p);
    Se fai:

    System.out.println(oggetto.toString());

    stai invocando TU toString() e stai passando un String alla versione di println che è definita come

    public void println(String x)

    che quindi "sa" solo di dover ricevere un String e basta.

    Se invece fai:

    System.out.println(oggetto);

    stai passando un qualunque oggetto all'altra versione di println che è definita come

    public void println(Object x)

    che sa di ricevere un qualunque oggetto e siccome deve stampare una descrizione dell'oggetto invoca toString() sull'oggetto.

    A livello di risultato finale è UGUALE. Cambia solo CHI invoca toString(). Nel primo caso tu, nel secondo caso la invocazione di toString() è dentro il println.


    P.S. non lo dico per critica ma questa discussione sta quasi diventando una specie di mini-corso tra Ansharja e te. Se hai dubbi specifici su certe questioni o argomenti, apri un'altra discussione più precisa e pertinente. Così altri (e io) possiamo rispondere in modo più puntuale, senza dover rileggere 3 pagine di discussione ..
  • Re: Aiutino per richiamare metodi di altre classi?

    xXNicolaXx ha scritto:


    Scelta avevo provato a metterla dentro il metodo ma mi dava errore...ho capito ora che bastava togliere il private, perchè in effetti non ha senso(infatti mi dava come errore "illegal start of expression". L'ho messo prima del do...come mai se la metto dentro il do, prima dell'inserimento da tastiera, mi da errore sulla riga del while sottolineando "scelta" dove c'è scritto scelta.equals("1") ecc? Come se non trova scelta...
    Una variabile è visibile localmente a dove è definita. Se la definisci come membro della classe ha senso scegliere se metterla private,public etc.
    Se la definisci in un metodo è visibile solo all'interno del metodo, quindi come hai capito non ha senso scrivere private, lì è un errore.
    Ma se la definisci all'interno del ciclo do, ancora una volta è visibile solo dentro il ciclo, quindi la condizione del while, che è esterna alle graffe che racchiudono la definizione di scelta, non capisce cosa sia scelta.

    xXNicolaXx ha scritto:


    Inoltre questo toString, invece che mettendo la stampa di "nome" + "cognome" ecc..si poteva fare facendo stampare il vettore? Cioè, mettendo return passeggeri[cont]?
    La parte precedente su chi richiama il toString() l'ha già spiegata andbin.
    Questo dubbio invece non dovresti più averlo, all'interno di Passeggero il vettore passeggeri non è e non deve essere definito, il Passeggero singolo è solo contenuto all' interno del vettore, ma non ne ha la minima idea, sono due classi slegate Registrazione e Passeggero.

    xXNicolaXx ha scritto:


    Poi non ho capito ancora una cosa..nel costruttore di passeggero..se abbiamo detto che numero è = a numeroPasseggeri e viene incrementato numeroPasseggeri..perchè dal toString() se invece che far stampare il numero faccio stampare numeroPasseggeri, mi stampa tutti i numeri uguali?
    Cioè, se metto 3 passeggeri stampa a ogni passeggero il numero 3.
    Mentre se lascio la variabile numero allora stampa 0,1,2 ovvero correttamente.
    Questo dipende dal fatto che la variabile numeroPasseggeri è statica , cioè è comune a tutti gli oggetti Passeggero e non è specifica a un solo Oggetto.
    Se così non fosse (prova per esercizio a rimuovere lo static!!), alla creazione di ogni Passeggero verrebbe creata una nuova copia della variabile, che è inizializzata a 0, e quindi numero = numeroPasseggeri metterebbe 0 anche in numero, per ogni Passeggero (infatti la variabile la incrementi dopo).

    Essendo condivisa da tutti i Passeggero invece, quando una istanza modifica quella variabile la modifica vale per tutte le istanze, in questo modo la usi come un contatore.
    Ma nel toString () , se restituissi quella variabile, riceveresti sempre il numero di passeggeri creati all' istante in cui il toString viene richiamato.

    Se hai altri dubbi specifici sulle basi del linguaggio in effetti faresti bene a seguire il consiglio di aprire una nuova discussione, per renderla più facile da seguire
  • Re: Aiutino per richiamare metodi di altre classi?

    Se fai:

    System.out.println(oggetto.toString());

    stai invocando TU toString() e stai passando un String alla versione di println che è definita come

    public void println(String x)

    che quindi "sa" solo di dover ricevere un String e basta.

    Se invece fai:

    System.out.println(oggetto);

    stai passando un qualunque oggetto all'altra versione di println che è definita come

    public void println(Object x)

    che sa di ricevere un qualunque oggetto e siccome deve stampare una descrizione dell'oggetto invoca toString() sull'oggetto.

    A livello di risultato finale è UGUALE. Cambia solo CHI invoca toString(). Nel primo caso tu, nel secondo caso la invocazione di toString() è dentro il println.
    Capito, sei stato chiarissimo. Grazie per la spiegazione!
    P.S. non lo dico per critica ma questa discussione sta quasi diventando una specie di mini-corso tra Ansharja e te. Se hai dubbi specifici su certe questioni o argomenti, apri un'altra discussione più precisa e pertinente. Così altri (e io) possiamo rispondere in modo più puntuale, senza dover rileggere 3 pagine di discussione ..
    Si, hai perfettamente ragione. E' che ormai ero preso dal programma e volevo portarlo a termine a tutti i costi..mi avrebbe dato fastidio proprio a me stesso lasciarlo li a metà incompleto. Se una cosa mi piace, provo a farla finchè non ci riesco. In ogni caso, menomale che finalmente, dopo 3 giorni e 3 pagine di discussione, siamo riusciti a finire il programma(ora non mi rimane solamente che aggiungere dei controlli magari)
    Questo dipende dal fatto che la variabile numeroPasseggeri è statica , cioè è comune a tutti gli oggetti Passeggero e non è specifica a un solo Oggetto.
    Se così non fosse (prova per esercizio a rimuovere lo static!!), alla creazione di ogni Passeggero verrebbe creata una nuova copia della variabile, che è inizializzata a 0, e quindi numero = numeroPasseggeri metterebbe 0 anche in numero, per ogni Passeggero (infatti la variabile la incrementi dopo).

    Essendo condivisa da tutti i Passeggero invece, quando una istanza modifica quella variabile la modifica vale per tutte le istanze, in questo modo la usi come un contatore.
    Ma nel toString () , se restituissi quella variabile, riceveresti sempre il numero di passeggeri creati all' istante in cui il toString viene richiamato.
    capito, grazie ancora per l'ennesima spiegazione
    Se hai altri dubbi specifici sulle basi del linguaggio in effetti faresti bene a seguire il consiglio di aprire una nuova discussione, per renderla più facile da seguire
    Si è vero...
    Non so veramente come ringraziarti. Sei riuscito, insieme a andbin, a insegnarmi le basi di java in poco tempo e mi hai praticamente risolto il programma!
    Grazie mille davvero! Alla prossima
Devi accedere o registrarti per scrivere nel forum
40 risposte