PDA

View Full Version : [JAVA] perche' l'output è .... ?


Tony Hak
04-02-2008, 10:27
ragazzi .. aiutatemi a capire perche' come output ho MiaData: 30-4-1964 .. magari passaggio per passaggio .. perche' ci sto perdendo la testa.. Le due classi sono :

public class Testmiadata {
public static void main(String[] args) {
MiaData nascita = new MiaData(23,4,1964);
MiaData la_settimana_dopo = nascita.addgiorni(7);
la_settimana_dopo.print();
}

}

e ...

public class MiaData
{
private int giorno = 1;
private int mese = 1;
private int anno = 2006;

public MiaData (int giorno, int mese, int anno)
{
this.giorno = giorno;
this.mese = mese;
this.anno = anno;
}

public MiaData (MiaData data)
{
giorno = data.giorno;
mese = data.mese;
anno = data.anno;
}

public MiaData addGiorni (int g)
{
MiaData data = new MiaData (this);
data.giorno = data.giorno + g;
return data;
}

public void print()
{
System.out.println ("MiaData: "+giorno+"-"+mese+"-"+anno);
}
}

grazie mille ;)

Il.Socio
04-02-2008, 10:48
Quale output ti saresti aspettato di ottenere?

Tony Hak
04-02-2008, 11:05
no asp .. ora ti spiego ..allora ... questo è un esempio dagli appunti del mio prof .. solo che non capisco come esce questo output... non ho capito bene il procedimento generale..

Il.Socio
04-02-2008, 11:20
Il procedimento generale che e' stato seguito e' questo:
- viene creata una istanza di MiaData attribuendogli valore iniziale di 23-4-1964.
- si ottiene una nuova istanza di MiaData aggiungendo 7 giorni alla prima istanza
- si stampa il valore contenuto nella nuova istanza di MiaData (30-4-1964 che altro non e' che il risultato di 23+7)

Ma scommetto che non e' questo che ti interessava sapere...

feboss
04-02-2008, 11:40
MiaData nascita = new MiaData(23,4,1964);
crea un oggetto nascita di tipo miaData.quindi va a chiamare la classe e passa come paramentri gg/mm/aa

MiaData la_settimana_dopo = nascita.addgiorni(7);
crea un altro oggetto la_settimana_dopo sempre di tipo MiaData e gli assegna il return di addgiorni(int)

public MiaData addGiorni (int g)
{
MiaData data = this;
data.giorno = data.giorno + g;
return data;
}
con this si intende la classe che la ha invocata. nascita.addGiorni(7);
quindi nascita
data è la copia di nascita in questo caso

MiaData data = this è uguale a MiaData data = new MiaData (this);

Tony Hak
04-02-2008, 12:03
ok ! tnk's ... ora mi è tutto piu' chiaro .. grazie ancora...

Tony Hak
04-02-2008, 12:04
Il procedimento generale che e' stato seguito e' questo:
- viene creata una istanza di MiaData attribuendogli valore iniziale di 23-4-1964.
- si ottiene una nuova istanza di MiaData aggiungendo 7 giorni alla prima istanza
- si stampa il valore contenuto nella nuova istanza di MiaData (30-4-1964 che altro non e' che il risultato di 23+7)

Ma scommetto che non e' questo che ti interessava sapere...

era un po' tutto .. ma soprattutto il this ... cmq ora sto capendo grazie a voi :)

Il.Socio
04-02-2008, 12:05
MiaData data = this è uguale a MiaData data = new MiaData (this);
Credo proprio che tu stia facendo confusione e che stia a tua volta portando confusione nella discussione...
I due costrutti che hai riportato non sono affatto uguali e le implicazioni sono anche notevoli, ti tralascio la spiegazione per evitare inutili divagazioni e ti invito a verificare "sul campo" il codice che hai scritto, ad es. richiamando il nascita.print() per entrambi i casi

P.S. Non ho trovato un modo maggiormente "soft", il post e' da leggere ammorbidendo qua e la dove io non sono riuscito.

Tony Hak
04-02-2008, 12:17
quindi ? :confused:

banryu79
04-02-2008, 12:26
Comunque, a beneficio di Tony Hak, "this" è il riferimento implicito all'istanza di classe corrente.

Ad esempio:

public class Pippo {

int anni;
int occhi;


// costruttore
public Pippo() {
// di default decido che Pippo ha 10 anni e 2 occhi
anni = 10;
occhi = 2;
}


// costruttore con parametro
public Pippo(int anni) {
// utilizzo this
this.anni = anni;

occhi = 2; // sempre due occhi. in questo caso posso omettere this
}


// costruttore con tutti i parametri
public Pippo(int anni, int occhi) {
// utilizzo this
this.anni = anni;
this.occhi = occhi;
}

}//end Pippo


Come vedi non sempre serve specificare this...

Nei casi in cui, in un metodo, un parametro preso ingresso vada assegnato ad un attributo della classe e il nome del parametro formale coincida con quello dell'attributo, this va necessariamente utilizzato per poter distinguere il parametro passato al metodo dall'attributo della classe.

Oltre a this esiste un'altro riferimento implicito di classe, "super".

"this" torna un riferimento all'istanza di classe corrente;
"super" torna un riferimento alla classe padre dell'istanza di classe corrente.

Ho messo in grassetto istanza perchè questo è un dettaglio importante: le classi possono contenere, oltre ai metodi di istanza (cioè è necessaria l'esistenza di un oggetto di quella classe per chiamarli, e il metodo è chiamato su quell'oggetto), dei metodi statici: questi sono metodi che non richiedono l'esistenza di un oggetto di classe per essere chiamati, perchè non sono chiamati tramite un'istanza della classe, ma sono metodi della classe stessa e non degli oggetti.

Non essendo necessaria la creazione di un'istanza della classe per l'invocazione di questi metodi, è chiaro che al loro interno non si può utilizzare "this", proprio perchè non esiste alcuna istanza specifica a cui fare riferimento.
Sempre per la medesima ragione, dentro a metodi statici si possono referenziare/chiamare/utilizzare solo attributi statici e metodi statici.

Il.Socio
04-02-2008, 12:58
quindi ? :confused:
Ammesso che il tuo scopo sia comprendere la logica che c'e' dietro, dovresti cercare di spiegare quali sono i concetti che non ti sono chiari o su cui incontri dei problemi...
Il procedimento generale che e' stato adottato ora dovrebbe essere chiaro, quali sono gli altri dubbi?

Il.Socio
04-02-2008, 13:05
era un po' tutto .. ma soprattutto il this
this identifica l'istanza corrente.
In riferimento a

public Pippo(int anni) {
this.anni = anni; // utilizzo this
occhi = 2; // sempre due occhi. in questo caso posso omettere this
}

viene utilizzato per distinguere tra la proprieta anni appartenente all'istanza ed il valore del parametro anni passato in input al costruttore...
Questo tipo di approccio e' generalmente sconsigliato, ed e' preferibile scrivere piuttosto:

public Pippo(int degliAnni) {
anni = degliAnni;
occhi = 2; // sempre due occhi. in questo caso posso omettere this
}

In modo da omettere l'utilizzo non indispensabile di this ed evitare deltutto ogni tipo di ambiguita'.


In questo contesto viene creata una nuova istanza di MiaData:

MiaData data = new MiaData (this);


richiamando il secondo costruttore di MiaData (che in pratica consente di creare una copia dell'oggetto)

public MiaData (MiaData data)
{
giorno = data.giorno;
mese = data.mese;
anno = data.anno;
}

a cui viene passato come parametro l'istanza corrente (identificata con this)

Tony Hak
04-02-2008, 13:13
allora... prima di tutto ringrazio tutti ..seconda cosa .. il concetto che non mi era chiaro er al'uso di this..e poi .. new (xxx) crea la classe assegnando valore agli attributi ... ma poi richiama anche il costruttore ?

Il.Socio
04-02-2008, 13:38
Ogni volta che crei una istanza con new, cio' comporta la chiamata ad un qualche costruttore associato (puo' essere presente piu' di un costruttore).

Il costruttore che sara' richiamato dipende dal tipo e dal numero di parametri che vengono passati in fase di creazione dell'istanza.
Es. il codice:
MiaData prova = new MiaData(1, 2, 1900);
provoca la chiamata ad un qualche costruttore che prende in input 3 parametri di tipo intero.
Quindi sara' richiamato il primo costruttore:
public MiaData (int giorno, int mese, int anno)

Se dopo prosegui scrivendo:
MiaData nuovaData = new MiaData(prova);
questo comporta la chiamata ad un qualche costruttore che prende 1 solo parametro di tipo MiaData.
Quindi sara' richiamato il secondo costruttore:
public MiaData (MiaData data);

Se continui ancora scrivendo:
MiaData koData = new MiaData(1, 2);
questo generera' un'errore in fase di compilazione perche' nella classe MiaData non e' stato definito alcun costruttore che prende 2 parametri di tipo intero.

Tony Hak
04-02-2008, 13:42
ok ... capito .. ma quindi quando faccio come hai detto tu new (2,3 ,4) ad esempio ... c'e' la chiamate e quindi l'esecuzione del costruttore..giusto ? ..e senti .. se in una classe non ci sono costruttori ,c'e' il costruttore di default. la chiamata a new (xxx) provoca errore ? e come si fa achiamare il cotruttore di default di una classe ?

Il.Socio
04-02-2008, 13:59
ok ... capito .. ma quindi quando faccio come hai detto tu new (2,3 ,4) ad esempio ... c'e' la chiamate e quindi l'esecuzione del costruttore..giusto ?
Hai capito perfettamente :)

..e senti .. se in una classe non ci sono costruttori ,c'e' il costruttore di default. la chiamata a new (xxx) provoca errore ?
Si, provoca errore perche' nella classe non e' stato definito nessun costruttore che prende in input un parametro di tipo xxx.
Cfr. precedente esempio MiaData koData = new MiaData(1,2)

e come si fa achiamare il cotruttore di default di una classe ?
Il costruttore di default non prende alcun parametro di alcun tipo, quindi per richiamarlo, dovrai scrivere qualcosa del tipo MiaData prova = new MiaData();
pero' considera che nel momento in cui definisci anche 1 solo costruttore, quello di default va "a perdersi", quindi nel tuo codice non e' possibile richiamare quello di default, sarebbe possibile se tu eliminassi i due costruttori che hai definito, o in alternativa, potresti definire in MiaData un nuovo costruttore che non prende alcun parametro di alcun tipo public MiaData() {}

Tony Hak
04-02-2008, 15:12
ok ... ok .. allora io faccio "new chiama()" per richiamare il costruttore di default....che succede ? cosa va in esecuzione ? la classe contenente il costruttore di default ?

Il.Socio
04-02-2008, 18:09
Non sono certo di aver capito l'entita' del tuo dubbio...
Il nome del costruttore deve necessariamente rispecchiare quello della classe a cui appartiene ed e' l'unico metodo per cui non viene mai dichiarato il tipo del valore di ritorno...
es: public MiaData() {}
e' un costruttore della classe MiaData.

Non essendo stata definita una classe nominata "chiama" ti sara' segnalato un errore in fase di compilazione...

k0nt3
04-02-2008, 22:59
ok ... ok .. allora io faccio "new chiama()" per richiamare il costruttore di default....che succede ? cosa va in esecuzione ? la classe contenente il costruttore di default ?

se non hai definito nessun costruttore e chiami il costruttore di default viene il chiamato il costruttore di Object. perchè tutte le classi sono sottoclassi dalla classe Object.

Tony Hak
05-02-2008, 13:08
se non hai definito nessun costruttore e chiami il costruttore di default viene il chiamato il costruttore di Object. perchè tutte le classi sono sottoclassi dalla classe Object.

ecco ! ehm .. e cosa fa il costruttore di Object ? ...:mc:

AnonimoVeneziano
05-02-2008, 13:26
ecco ! ehm .. e cosa fa il costruttore di Object ? ...:mc:

Beh, essenzialmente niente :D

Comunque in realtà se non specifichi nessun costruttore ne viene creato uno di default che come unica azione fa quella di chiamare il costruttore di Object. Se la classe non ha bisogno i propri attributi vengano inizializzati in genere non viene fornito nessun costruttore e viene usato quello di default "NomeClasse()"

Ciao