Como han dicho otros, las variables privadas son buenas para evitar usos erróneos que llevan al objeto a un estado inconsistente y a errores difíciles de rastrear y excepciones imprevistas.
Pero, por otro lado, lo que los demás han ignorado en su mayor parte es sobre los campos protegidos.
Una subclase extendida tendrá acceso completo a los campos protegidos, haciendo que el objeto sea tan frágil como si dichos campos fueran públicos, pero esa fragilidad se limita a la clase extendida por sí misma (a menos que exponga aún más dichos campos).
Por lo tanto, los campos públicos son difíciles de considerar buenos, y hasta la fecha, la única razón para usarlos es para las clases utilizadas como parámetro de configuración (una clase muy simple con muchos campos y sin lógica, por lo que esa clase se pasa como un parámetro solo a algún método).
Pero, por otro lado, los campos privados reducen la flexibilidad de su código a otros usuarios.
Flexibilidad frente a problemas, pros y contras:
Los objetos instanciados por su código en la clase vainilla con campos protegidos son seguros y son de su exclusiva responsabilidad.
Por otro lado, los objetos que amplían su clase con campos protegidos, instanciados por los usuarios de su código, son su responsabilidad, no la suya.
Por lo tanto, los campos / métodos protegidos no están bien documentados, o si los usuarios realmente no entienden cómo se deben usar dichos campos y métodos, tienen una buena posibilidad de causar problemas innecesarios para ellos y para usted.
Por otro lado, hacer que la mayoría de las cosas sean privadas reducirá la flexibilidad de los usuarios, e incluso puede alejarlos en busca de alternativas mantenidas, ya que es posible que no quieran crear y mantener una bifurcación solo para que las cosas sucedan a su manera.
Por lo tanto, un buen equilibrio entre privado, protegido y público es lo que realmente importa.
Ahora, decidir entre privado y protegido es el verdadero problema.
¿Cuándo usar protegido?
Cada vez que comprenda que un campo puede ser muy flexible, debe codificarse como protegido. Esa flexibilidad es: desde convertirse en nulo (donde nulo siempre se verifica y reconoce como un estado válido que no arroja excepciones), hasta tener restricciones antes de ser utilizado por su clase ex. > = 0, <100, etc., y se corrige automáticamente para valores de flujo excesivo / insuficiente, lanzando como máximo un mensaje de advertencia.
Entonces, para dicho campo protegido, podría crear un captador y solo usarlo (en lugar de usar directamente la variable de campo), mientras que otros usuarios pueden no usarlo, en caso de que quieran más flexibilidad para su código específico, en mi ejemplo podría ser como : si quieren que los valores negativos funcionen bien en su clase extendida.