Il concetto e' abbastanza semplice: e' tutta questione di 'filosofia'.
Considera l'oggetto (un intero) '33' (trentatre): questo e' un oggetto ATOMICO, cioe' non ulteriormente suddivisibile, anche se, volendo, lo potresti vedere come l'insieme di DUE cifre decimale.
Ma nel 99.9999% dei casi, non ti interessa sapere di quante cifre e' composto, ma solo del suo valore (medico al paziente: 'dica trentatre')
Ora pensa ad una casella della scacchiera (dama, scacchi, ...), oppure ad un punto su un foglio di carta millimetrata: quella casella o quel punto avranno ben determinate coordinate ('riga 3, colonna=A', 'x=3, y=3').
Consideriamo il caso della carta millimetrata: ti serve un oggetto Java per rappresentare quel 'punto': supponiamo, guarda i casi della vita, che questo oggetto tu lo voglia rappresentare mediante una classe, dal nome 'Punto' e da due membri, 'x' e 'y', che rappresentano le 'coordinate cartesiane' di quel punto (x=3, y=3).
E qui' sta la parte 'filosofica': come vuoi 'considerare' una 'istanza' della classe Punto (ad esempio il punto con coordinate x=3, y=5)?
Ci sono due possibilita':
1) come un oggetto ATOMICO, cioe' indivisibile, immutabile, come il '33' di prima, formato da DUE numero (x=3, y=5), ma che rimarranno quelli per tutta la vita di quell'oggetto, e quindi se ti serve il punto (x=120,y=33), DEVI creare un nuovo oggetto, ed in questo caso scriveresti
p1=new Point(3,5);
p2=new Point(120,33);
OPPURE
2) come un CONTENITORE, uno scatolotto che OGGI contiene i valori x=3 e y=5, ma un domani potrebbe contenere i valori x=120,y=33, ed in questo caso scriveresti:
p1=new Point(3,5);
p2=p1; p2.setx(120); p2.sety(33);
Ora, OSSERVA BENE questo secondo esempio (che puoi provare a scrivere in Java).
p2 e' il punto di coordinate (x=120,y=33), ma QUALI coordinate sono rappresentate dal punto p1?
Come scoprirai con piacere/ORRORE, p1 ha ESATTAMENTE le coordinate di p2 (x=120,y=33)!
Ma p1 non doveva essere il punto di coordinate x=3,y=5?
La questione filosofica sta' tutta qui!
Se
1) vuoi SCONGIURARE ASSOLUTAMENTE questa situazione (e nel caso di Punto, ha perfettamente senso), allora il tuo oggetto deve venir inizializzato SOLO passando i parametri al costruttore
2) il tuo oggetto e' un CONTENITORE e quindi, come tale, ti servono i metodi setter (setx(), sety() ) per cambiare i valori CONTENUTI di x e y.
La presenza dei 'getter' ('getx()', 'gety()') NON E' OBBLIGATORIA: e' comoda, perche ti puo' servire per SMONTARE l'oggetto Punto in ALTRE PARTI del programma, ma se ti vuoi assicurare che NESSUNO possa accedere alle coordinate, ecco che NON DEVI fornire i metodi getter.
Quindi, ricapitolando:
a) i metodi 'setter' si definiscono SE vuoi che il tuo oggetto sia un CONTENITORE e non un OGGETTO ATOMICO
b) i metodi 'getter' si definiscono SE vuoi che CHIUNQUE possa accedere alle informazioni INTERNE del tuo oggetto.
Questo concetto 'filosofico' si chiama
information hiding /
incapsulamento
Ed ora un ultimo passetto:
ma PERCHE' devo usare dei metodi getter e setter per poter cambiare o leggere i valori di x e y?
Perche' non posso scrivere semplicemente:
p1 = new Point();
p1.x = 3; p1.y = 5;
p2 =p1; p2.x = 120; p2.y= 33;
(in questo caso STO COSCIENTEMENTE consideranto Point come un CONTENITORE !!!) ?
Per fare questo e' semplice: basta rendere x e y
public.
In realta' non c'e' NESSUNO che te lo impedisca: e' di nuovo una questione 'filosofica'.
L'uso di metodi per accedere ai dati interni di un oggetto ti apre la possibilita', un domani, di poter aggiugere delle logiche extra nell'accesso a tali valori, cosa che, evidentemente, non puoi fare se accedi ai dati interni direttamente.