Come affermato da altri, le variabili private sono buone per evitare errori di utilizzo che portano l'oggetto in uno stato incoerente e difficili da tracciare bug ed eccezioni impreviste.
Ma d'altra parte, ciò che è stato per lo più ignorato dagli altri riguarda i campi protetti.
Una sottoclasse estesa avrà pieno accesso ai campi protetti, rendendo l'oggetto fragile come se tali campi fossero pubblici, ma la fragilità è limitata alla classe estendentesi (a meno che non esponga tali campi ancora di più).
Quindi, i campi pubblici sono difficili da considerare buoni, e alla data l'unica ragione per usarli è per le classi usate come parametri di configurazione (una classe molto semplice con molti campi e nessuna logica, così che la classe viene passata come parametro solo per qualche metodo).
Ma d'altra parte, i campi privati riducono la flessibilità del tuo codice agli altri utenti.
Flessibilità contro problemi, pro e contro:
Gli oggetti istanziati dal tuo codice nella classe vanilla con campi protetti sono al sicuro e sono di tua esclusiva responsabilità.
D'altra parte, gli oggetti che estendono la tua classe con campi protetti, istanziati dagli utenti del tuo codice, sono di loro competenza, non i tuoi.
Quindi, campi / metodi protetti non ben documentati, o se gli utenti non capiscono veramente come dovrebbero essere usati tali campi e metodi, hanno buone probabilità di causare problemi inutili a loro stessi e a te.
D'altra parte, rendere privata la maggior parte delle cose ridurrà la flessibilità degli utenti, e potrebbe anche metterli alla ricerca di alternative mantenute, poiché potrebbero non voler creare e mantenere un fork solo per fare in modo che le cose accadano.
Quindi, un buon equilibrio tra privato, protetto e pubblico è ciò che conta davvero.
Ora, decidere tra privato e protetto è il vero problema.
Quando utilizzare protetto?
Ogni volta che capisci che un campo può essere estremamente flessibile, dovrebbe essere codificato come protetto.
Questa flessibilità è: da diventare nullo (dove nullo è sempre controllato e riconosciuto come uno stato valido che non genera eccezioni), ad avere vincoli prima di essere usato dalla classe ex. > = 0, < 100 ecc. E riparato automaticamente per valori sovra / sotto-flussi, generando al massimo un messaggio di avviso.
Quindi, per tale campo protetto potresti creare un getter e usarlo solo (invece di usare direttamente la variabile di campo), mentre altri utenti potrebbero non usarlo, nel caso volessero una maggiore flessibilità al loro codice specifico, nel mio esempio potrebbe essere come: se vogliono che i valori negativi funzionino bene nella loro classe estesa.