DOMANDA [JAVA] Dubbio nell’uso di this

_Marco_123

Nuovo Utente
Ho un dubbio nell’uso di this in Java.
Avendo questo esempio,
Java:
public class Cliente{
private String nome, indirizzo;

public void setDati (String nome, String indirizzo){
this.nome=nome;
this.indirizzo=indirizzo;
}
}
E avendo anche quest altro esempio,
Java:
public class Cliente{
private String nome, indirizzo;

public void setIndirizzo(String indirizzo){
this.indirizzo =indirizzo;
}
public void setNome(String nome){
this.nome =nome;
}
}
perché non posso dire siano uguali?
Secondo il mio testo da cui ho preso questi esempi , il secondo non mi darà il risultato corretto. A me però sembrano uguali :pazzo::pazzo:
 
Ultima modifica da un moderatore:

_Marco_123

Nuovo Utente
Perché si usa solitamente un costruttore per richiamare i metodi get e set di ogni variabile da inizializzare ,quando si potrebbe fare tutto in un unica funzione(metodo) come nel primo esempio. Per capirci, vedo spesso usare codici del tipo:
Java:
public class Cliente{
        private String nome, indirizzo;
public Cliente(String nome, String indirizzo){. //richiamando il costruttore
       this.setNome(nome);
       this.setIndirizzo(indirizzo);
}
public void setNome(String nome){.  //per la variabile nome
   this.nome=nome;
}
public void setIndirizzo(String indirizzo){. //per la variabile indirizzo
   this.indirizzo=indirizzo;
}
}
 
Ultima modifica da un moderatore:

fabio93

Utente Attivo
451
130
Hardware Utente
CPU
AMD Ryzen 5 2400G
Dissipatore
Arctic Alpine64 Plus
Scheda Madre
Gigabyte GA-AX370-Gaming 3
Hard Disk
Crucial MX500 250 GB, Crucial BX500 240 GB
RAM
G.Skill F4-3200C14D-16GFX FlareX 16 GB
Monitor
HP 2010i
Alimentatore
Corsair TX550M
Case
Sharkoon M25-W
Periferiche
Magicforce 68, Logitech G203
Sistema Operativo
Windows 10 Pro, Fedora 31
perché si usa solitamente un costruttore per richiamare i metodi get e set di ogni variabile da inizializzare ,quando si potrebbe fare tutto in un unica funzione(metodo) come nel primo esempio.
Perché il costruttore viene invocato automaticamente alla creazione di un nuovo oggetto, quindi, inserendo le chiamate dei setter (non tanto dei getter) al suo interno ci si assicura che essi vengano invocati, e che ciò non sia demandato all'iniziativa del programmatore.
 

Andretti60

Utente Èlite
3,798
2,561
Hardware Utente
Alla prima domanda, anche a me pare che i due esempi siano corretti, in entrambi viene usato il keyword “this” per indicare la corrente istanza della classe. In questo caso è obbligatorio in quanto i parametri dei metodi hanno lo stesso nome dei campi della classe.
Che risultati hai?

La seconda domanda invece dipende da come si usa la classe, questo è valido per tutti i linguaggi, in genere le classi hanno diversi costruttori a seconda di come la classe viene usata. Dal punto di vista formale, inizializzare una istanza di una classe con dei valori oppure riempirli in seguito è la stessa cosa.
 
  • Mi piace
Reactions: dev_java

BAT00cent

Utente Attivo
1,022
453
Hardware Utente
this è il riferimento implicito all'oggetto che invoca un determinato metodo;
l'unica differenza pratica nella classe Cliente è che, per impostare i dati (nome, indirizzo), se implementi la prima versione dovrai invocare un solo metodo, nella seconda versione ne invochi due.
C'è un però: sebbene siano entrambe corrette è meglio la versione con i 2 metod set separati, in quanto hai 2 attributi, ciascuno dei quali dovrebbe avere un metodo set (individuale); è una questione sia stilistica che di leggibilità ed è migliore dal punto di vista della manutenzione del codice.
I metodi set possono o meno essere usati nei costruttori, dipende da come decidi di organizzare la classe;
nel tuo caso tu non hai definito costruttori di classe, perciò Java ne crea automaticamente uno predefinito che ti istanzia a null gli attributi di tipo oggetto come le stringhe (0 o 0.0 i numeri, false i boolean, carattere nullo i caratteri); questo significa che se crei un Cliente con new, esso ha nome ed indirizzo null; se invece definisci un costruttore con parametri, dovrai invocare i metodi set per impostare i dati; in alternativa puoi mettere direttamente nel costruttore istruzioni come this.nome=nome, di solito non si fa perché è una inutile duplicazione di codice; inoltre, se caso decidi di modificare il modo con cui si impostano gli attributi, modificherai solo il relativo metodo set.
Questo modo di procedere è anche il motivo per cui Java viene spesso etichettato come linguaggio eccessivamente verboso, perché per fare le cose "per bene" c'è da scrivere parecchio codice. Bisogna anche dire che gli IDE in genere dispongono di strumenti di generazione automatica di metodi get/set per gli attributi di classe, per cui anche se è vero che si genera parecchio "scritto" è anche vero che molto può essere automatizzato dagli strumenti di sviluppo.
Post automaticamente unito:

 
Ultima modifica:

_Marco_123

Nuovo Utente
Grazie Mille!!!:luxhello::love::thanks::thanks::thanks:
Post automaticamente unito:

Solo per chiarire , in questo codice che ho scritto riguardo una classe Docente
Schermata 2020-02-24 alle 18.58.18.png


è giusto il costruttore Docente(String nome, String cognome, int codice, int eta)?
E se invece nel secondo costruttore Docente(Docente d), scrivessi:

public Esame1(Esame1 d){
this.getNome(nome);;
this.getCognome(cognome);
this.getCodice(codice);
this.getEta(eta);
}

sarebbe sbagliato??

(P.S scusate le troppe domande :help:).
 
Ultima modifica:

fabio93

Utente Attivo
451
130
Hardware Utente
CPU
AMD Ryzen 5 2400G
Dissipatore
Arctic Alpine64 Plus
Scheda Madre
Gigabyte GA-AX370-Gaming 3
Hard Disk
Crucial MX500 250 GB, Crucial BX500 240 GB
RAM
G.Skill F4-3200C14D-16GFX FlareX 16 GB
Monitor
HP 2010i
Alimentatore
Corsair TX550M
Case
Sharkoon M25-W
Periferiche
Magicforce 68, Logitech G203
Sistema Operativo
Windows 10 Pro, Fedora 31
I metodi getter non dovrebbero avere alcun parametro di ingresso, dato che il loro scopo è restituire il valore di un attributo (e infatti il parametro che hai indicato in ciascuno di essi non è utilizzato).
Il costruttore Docente con in input un oggetto di classe Docente, se ho ben inteso, serve a inizializzare l'oggetto Docente corrente con lo stato di quello passatogli come parametro. In questo caso, nel corpo del costruttore, tutti i metodi chiamati a destra delle assegnazioni dovrebbero essere invocati sull'oggetto passato come parametro, non su quello corrente, come hai fatto alla prima assegnazione (nome = d.getNome()).
Non ho capito l'ultima domanda.
 
  • Mi piace
Reactions: BAT00cent

_Marco_123

Nuovo Utente
Allora la consegna chiedeva questo :
Scrivere una classe Docente che rappresenti le seguenti informazioni relative ad un docente: nome, cognome, codice ed età, e che contenga il costruttore parametrizzato ed i metodi getCodice, getCognome e getEta che restituiscono rispettivamente il codice, il cognome e l’età del docente.
Allora ho fatto:

Java:
public class Esame1{
    private String nome;
    private String cognome;
    private int codice;
    private int eta;

    public Esame1(String nome, String cognome, int codice, int eta){
        this.nome=nome;
        this.cognome=cognome;
        this.codice=codice;
        this.eta=eta;
    }

    public Esame1(Esame1 d){
    this.getNome();
    this.getCognome();
    this.getCodice();
    this.getEta();
    }


    public String getNome(){
        return nome;
    }

    public String getCognome(){
        return cognome;
    }
    
    public int getCodice(){
        return codice;
    }
    
    public int getEta(){
        return eta;
    }

}
Ho aggiustato i metodi get , togliendo il parametro come suggerito da @fabio93 .
Il problema è che nella soluzione dell'esercito i due costruttori sono impostati diversamente cioè:

Java:
public Docente(String n, String c, int cod, int e){
nome=n;
cognome=c;
codice=cod;
eta=e;
}
public Docente(Docente d){
nome=d.getNome(); 
cognome=d.getCognome(); 
codice=d.getCodice(); 
eta=d.getEta();
}
quindi è completamente sbagliato il mio codice o va anche bene?
 

DispatchCode

Utente Attivo
636
397
Hardware Utente
CPU
Intel i7 6700HQ, 2.60Ghz, 4 core 8 threads
Scheda Madre
Asustek
Hard Disk
Hitachi 7200 rpm, 1TB
RAM
16GB DDR4 (2 slot su 4)
Scheda Video
Nvidia Geforce GTX 960M, 4GB
Scheda Audio
Realtek
Sistema Operativo
Windows 10 64bit
Allora la consegna chiedeva questo :
Scrivere una classe Docente che rappresenti le seguenti informazioni relative ad un docente: nome, cognome, codice ed età, e che contenga il costruttore parametrizzato ed i metodi getCodice, getCognome e getEta che restituiscono rispettivamente il codice, il cognome e l’età del docente.
Allora ho fatto:

Java:
public class Esame1{
    private String nome;
    private String cognome;
    private int codice;
    private int eta;

    public Esame1(String nome, String cognome, int codice, int eta){
        this.nome=nome;
        this.cognome=cognome;
        this.codice=codice;
        this.eta=eta;
    }

    public Esame1(Esame1 d){
    this.getNome();
    this.getCognome();
    this.getCodice();
    this.getEta();
    }


    public String getNome(){
        return nome;
    }

    public String getCognome(){
        return cognome;
    }
   
    public int getCodice(){
        return codice;
    }
   
    public int getEta(){
        return eta;
    }

}
Ho aggiustato i metodi get , togliendo il parametro come suggerito da @fabio93 .
Il problema è che nella soluzione dell'esercito i due costruttori sono impostati diversamente cioè:

Java:
public Docente(String n, String c, int cod, int e){
nome=n;
cognome=c;
codice=cod;
eta=e;
}
public Docente(Docente d){
nome=d.getNome();
cognome=d.getCognome();
codice=d.getCodice();
eta=d.getEta();
}
quindi è completamente sbagliato il mio codice o va anche bene?
Si, il tuo codice è sbagliato.
Il primo costruttore può anche andar bene, ma vale quanto dicevano sopra. Il "this" fa riferimento all'istanza corrente, in pratica lo usi per accedere alle variabili della classe; quindi se fai:


Java:
    public Esame1(String nome, String cognome, int codice, int eta){
        this.nome=nome;
        this.cognome=cognome;
        this.codice=codice;
        this.eta=eta;
    }
il "this.nome" è la variabile che hai dichiarato nella classe, mentre "nome" è il parametro della funzione.

Il tuo secondo costruttore non ha senso però...se richiami

Java:
public Esame1(Esame1 d){
    this.getNome();
    this.getCognome();
    this.getCodice();
    this.getEta();
}
stai richiamando l'istanza corrente della classe su getNome() e gli altri metodi, che ovviamente non avranno dati al loro interno (se non i valori di default per stringhe e numeri). Inoltre stai anche scartando i risultati...

Se crei un'istanza leggendo un altro oggetto (il parametro d, nel tuo caso) dovrai anche ovviamente richiamare i metodi su di essa.
Quindi così:

Java:
public Docente(Docente d){
nome=d.getNome();
cognome=d.getCognome();
codice=d.getCodice();
eta=d.getEta();
}
 

BAT00cent

Utente Attivo
1,022
453
Hardware Utente
Premessa:
se ti chiedono di scrivere una classe Docente, tu devi chiamare la classe Docente, non "Esame1";
il codice che hai scritto in Esame1 (a parte il nome inappropriato per la classe) è corretto solo per il primo costruttore che prende tutti i parametri (nome, cognome ecc.);
il secondo costruttore che hai scritto è sbagliato; per come lo ha descritto dovrebbe creare un "nuovo" docente (nel tuo caso un nuovo Esame1) facendo la copia dei campi, però non hai messo l'istruzione di copia/assegnazione degli attributi
ERRATO: this.getNome();
CORREZIONE: devi assegnare il "nome" del parametro d all'attributo "nome" della copia creata dal costruttore, quindi
this.nome=d.getNome();
e così per gli altri attributi.

Per quanto riguarda la soluzione, come noterai c'è l'assenza del this; il motivo è nel nome dei parametri del costruttore
Codice:
public Docente(String n, String c, int cod, int e){
in questo caso
nome=n è esattamente equivalente a this.nome=n perché il nome del parametro è n (Stringa)
se il nome del parametro coincide con quello dell'attributo
Codice:
public Docente(String nome, ...){
il this è necessario per distinguere l'attributo di classe nome (=this.nome) dal nome del parametro (nome) per cui necessariamente l'istruzione deve essere
this.nome=nome

OPS.. ho risposto contemporaneamente a @DispatchCode
 

_Marco_123

Nuovo Utente
Credo di ever capito allora. Dopo vari tentativi sono giunto a dire che in questo caso usare nome=n; o this.nome=n; era equivalente, esattamente come precisato da te @BAT00cent, (per quanto riguarda il nome della classe , ho fatto copia-incolla e mi sono accorto solo dopo di averlo fatto sul file "Esame1", errore mio). Il dubbio più grande era sul secondo costruttore ma grazie anche a @DispatchCode penso di averlo ora più chiaro.
In sostanza non capisco al volo a quale istanza si fa riferimento in una determinata parte del codice e do ,per questo ,scontato che si faccia riferimento a un oggetto a cui in realtà non fa riferimento. Credo di dover riprendere il concetto di Scope per averlo più chiaro.
Comunque Grazie Mille :ok::ok::thanks:.
 

DispatchCode

Utente Attivo
636
397
Hardware Utente
CPU
Intel i7 6700HQ, 2.60Ghz, 4 core 8 threads
Scheda Madre
Asustek
Hard Disk
Hitachi 7200 rpm, 1TB
RAM
16GB DDR4 (2 slot su 4)
Scheda Video
Nvidia Geforce GTX 960M, 4GB
Scheda Audio
Realtek
Sistema Operativo
Windows 10 64bit
Credo di ever capito allora. Dopo vari tentativi sono giunto a dire che in questo caso usare nome=n; o this.nome=n; era equivalente, esattamente come precisato da te @BAT00cent, (per quanto riguarda il nome della classe , ho fatto copia-incolla e mi sono accorto solo dopo di averlo fatto sul file "Esame1", errore mio). Il dubbio più grande era sul secondo costruttore ma grazie anche a @DispatchCode penso di averlo ora più chiaro.
In sostanza non capisco al volo a quale istanza si fa riferimento in una determinata parte del codice e do ,per questo ,scontato che si faccia riferimento a un oggetto a cui in realtà non fa riferimento. Credo di dover riprendere il concetto di Scope per averlo più chiaro.
Comunque Grazie Mille :ok::ok::thanks:.
Si, per rendere la cosa più chiara, considera che quando dentro alla classe usi la parola chiave "this" è come se stessi dicendo "l'istanza corrente della classe"; quindi se fai "this.nome" stai dicendo "accedo al membro nome dell'istanza corrente".
I metodi e le variabili della classe (o variabili di istanza, no so come le chiami) sono i membri della classe. Per accedere ai membri (non privati) della classe usi un'istanza (un oggetto) della classe.
Quella variabile "d" è appunto un oggetto, e se richiami d.getNome() richiami il metodo getNome() sull'oggetto "d", accedendo, di fatto all'oggetto "d".
 
  • Mi piace
Reactions: Andretti60

Andretti60

Utente Èlite
3,798
2,561
Hardware Utente
In sostanza non capisco al volo a quale istanza si fa riferimento in una determinata parte del codice e do ,per questo ,scontato che si faccia riferimento a un oggetto a cui in realtà non fa riferimento. Credo di dover riprendere il concetto di Scope per averlo più chiaro.
No, lo Scope e' tutta un'altra cosa. Per Scope si intende la parte di codice dove una variabile (che puo' essere anche un metodo) e' valida perche' definita. Infatti si parla di "scope of a variable", la parola Scope da sola non ha senso.
Per esempio lo Scope della variabile 'this' (che e' una keyword speciale) e' tutto il corpo all'interno di una classe, e si riferisce all'oggetto (istanza) definito in quel preciso momento.
Secondo me il problema che stai avendo e' probabilmente dovuto al fatti che non hai capito bene la differenza tra 'class' e 'istanza'. Controlla il tuo libro di testo, se hai dubbi chiedi, perche' e' un concetto fondamentale.
Post automaticamente unito:

... Il dubbio più grande era sul secondo costruttore ...
Il costruttore e' uno dei principi chiave di una classe, perche' definisce come la classe venga creata, ponendo delle limitazioni sulla stessa.
Per esempio, nel tuo caso quando definisci un oggetto (istanza) della classe Docente, lo puoi creare cosi':
Java:
Docente d = new Docente();
d.Name = "Pippo";
d.Cognome = ...
E via dicendo. Questo puo' creare un serio problema (bug) nel codice, in quanto ti permette di creare un oggetto "vuoto", ossia senza attributi, se non ti ricordi di assegnare TUTTI i campi che sono obbligatori. Non solo, ma ti costringe a creare dei metodi 'SET' per assgnare valori a campi che non dovrebbero essere piu' riassegnati. Il cognome di un docente rimane sempre lo stesso (non proprio vero, ma partiamo da qui per il momento).
Ha quindi MOLTO piu' senso creare alle classi costruttori che permettano di potere definirne istanze senza ambiguita'. per esempio
Java:
Docente d = New Docente("Mario", "Rossi", 123456, 35);
In altre parole, il costruttore deve proprio "costruire" un oggetto con tutti gli attributi legali, quelli che non vanno cambiati.

Per migliorare il tuo codice (sto facendo didattica qui, non ha nulla a che fare con il tuo esercizio) assegnare l'eta' a una persona e' fondamentalmente sbagliato perche' ovviamente l'eta' cambia nel tempo. Saresti costretto a aggiornare i dati ogni mese :)
Sarebbe piu' corretto assegnare invece la data di nascita, e avere poi un metodo che la ritorna e un secondo metodo che ritorna l'eta' calcolando la differenza tra la data odierna e la data di nascita.

PS come ho detto altrove, questo non e' tipico di Java, fa parte della programmazione orientata a oggetti.
 
Ultima modifica:

_Marco_123

Nuovo Utente
Ed è proprio il this, o meglio l'istanza a cui fa riferimento che mi sfugge.La domanda che mi pongo sarebbe: se this fa riferimento all'oggetto istanziato dalla classe , perché allora non posso usarlo ovunque nel codice se fa riferimento sempre allo stesso oggetto(istanza)??
Questo ovviamente penso sia vero, a patto che non intanzi un altro oggetto (credo). L'uso del this sul mio libro di testo è spiegato un po' male, per questo sto avendo molti problemi e dubbi.
Per quanto riguarda il concetto di classe e istanza pensavo di averli chiari (ma forse come dici , non è cosi). Ho sempre considerato una classe come una sorta di insieme di caratteristiche (attributi) generali e di metodi che operano su questi; mentre le istanze (gli oggetti) come a una sorta di "prodotti" della classe che essendo creati da quest'ultima, possiedono a loro volta le sue stesse caratteristiche generali(i suoi stessi attributi o variabili d'istanza) .
Invece lo Scope se ho ben capito, non fa riferimento alla sola linea di codice in cui definisco una variabile o la uso, ma all'intero "contesto" su cui opera. Dunque essendo l'oggetto operante su tutta la classe perché è da essa creato, allo stesso modo il this (che fa riferimento all'oggetto) avrà come scope l'intera classe?
 

Entra

oppure Accedi utilizzando