Ci sono svariati motivi, tecnici e concettuali.
1) L'incapsulamento rientra in tutto un discorso più grande sul "information hiding", ovvero sul fatto di nascondere informazioni, dettagli interni, che non devono ("non dovrebbero") interessare a chi sta semplicemente usando una certa funzionalità esposta da una classe o altro.
Se una classe Persona ha un campo annoNascita (short), è importante che tu debba saperlo e poterci accedere direttamente? Generalmente no. Se ci puoi accedere direttamente, chi ha sviluppato quella classe (che potresti non essere tu), non potrebbe mai più cambiare il campo in es. un int o con un nuovo nome annoDiNascita. Se lo fa ... altro codice esterno si "spacca" e dovrebbe essere rimaneggiato e ricompilato.
Insomma, mantenere "nascosti" dettagli interni permette, tra le altre cose, di facilitare la evoluzione della classe, perlomeno di quella parte nascosta.
2) Se si permette l'accesso diretto ad un campo non si possono imporre "vincoli" sul valore (si chiamano "invarianti"). Le istruzioni di accesso al campo sarebbero sparpagliate ovunque venga usato quel campo e chi ha scritto la classe non ne avrebbe il controllo.
E se volessi fare in modo che il campo annoNascita NON possa essere mai minore di 1900? Lo puoi fare solo con l'incapsulamento, ovvero mettendo il campo private e offrendo i metodi "accessori" getter/setter public.
codice:public class Persona { private int annoNascita; public void setAnnoNascita(int annoNascita) { if (annoNascita < 1900) { throw new IllegalArgumentException("annoNascita non può essere minore di 1900"); } this.annoNascita = annoNascita; } public int getAnnoNascita() { return annoNascita; } }
Così l'invariante "l'anno di nascita deve sempre essere maggiore/uguale a 1900" è sempre garantito. Dimentichiamo un momento un uso "malizioso" della reflection, per cui sarebbe possibile accedere al campo anche se private. Ma in tutti gli altri usi normali, non c'è modo di sovvertire questo vincolo.
Senza incapsulamento, ovvero rendendo il campo accessibile, questo vincolo NON sarebbe possibile.
Ovviamente, se non hai un oggetto ..... non vedo cosa puoi settarci.
Dipende dal design e da chi si vuole che sia il "proprietario" dell'oggetto e del suo ciclo di vita.
Il tuo esempio è tecnicamente corretto.
Nei miei/tuoi esempi, public o non public cambia poco. Se non si specifica un modificatore di accesso (public/protected/private) il livello di accesso per i membri delle classi è quello di "default", cioè package-level. Siccome le classi sono nello stesso package, funziona sia public-level che package-level. Tecnicamente anche protected, se si vuole.
Come avevi prima Punto/Rettangolo come "inner class", un limite è che nel main NON potevi fare banalmente
Rettangolo rett= new Rettangolo();
Quel tuo codice iniziale non può compilare. E c'è un motivo: una inner class è particolare perché ha una relazione molto speciale con la classe "contenitore". Nel senso che una istanza della inner class deve essere associata ad una specifica istanza della classe contenitore. E nel tuo codice non avevi neanche una istanza di ProvaClasse.
Se ti interessa e continuerai lo studio di Java (ne hai tanto .. molto davanti ....) lo scoprirai. Ma per il momento il consiglio semplice è: ignora inner/nested class e non dichiarare mai classi (tipi in generale) dentro altri tipi. Fino a quando non arriverai all'argomento.![]()