jdk - java runtime environment
Campos protegidos de Java frente a getters públicos (7)
Qué es una mejor práctica y por qué: acceder a las variables de la clase base a través de un campo protegido o un getter público en el campo privado.
(El captador será público independientemente)
Algunas de las recomendaciones de Sun para controlar el acceso a los campos están here. Tenga en cuenta que hacer un campo protegido lo expone también al paquete, no solo a las subclases. En general, como se indica en el enlace anterior, los campos deben ser privados a menos que haya una muy buena razón para no hacerlo.
Effective Java 2nd Edition dice
Ítem 13: Minimice el acceso de clases y miembros
La regla de oro es simple: hacer que cada clase o miembro sea lo más inaccesible posible. En otras palabras, use el nivel de acceso más bajo posible consistente con el funcionamiento adecuado del software que está escribiendo.
Entonces, si no está seguro de por qué necesita un miembro protegido de la clase (es decir, no necesita que el campo sea accesible para subclases o clases en el mismo paquete), entonces declare que es privado. Si deseas configurarlo desde fuera de la clase, crea un setter público.
Sin embargo, si su miembro es final, protegerlo podría estar bien en algunos casos (es decir, no revela información confidencial).
Un problema potencial de seguridad que me gustaría mencionar es que si tiene una matriz declarada protegida final (incluso pública final), la matriz de referencia es definitiva (no puede ser modificada), pero los objetos contenidos en la matriz no son finales (un intruso podría cambiar el contenido de la matriz).
Si conoce c ++, probablemente sepa que
const int * someMember
es diferente de
int * const someMember
Este último es como el conjunto final en Java.
La solución para el agujero de seguridad antes mencionado es devolver una copia profunda de la matriz o devolverla como una lista de solo lectura.
El acceso a campos protegidos desde una subclase es una de las formas en que la herencia viola la encapsulación. Usar la API pública es mejor por esta razón.
En general, debe usar las recomendaciones de Sun. Hay una gran excepción: si estás programando para Android.
El motivo es el rendimiento. Con cada invocación de método virtual, hay una sobrecarga implicada en el uso de la tabla de búsqueda para encaminar el método a su objeto. Esta sobrecarga no está involucrada al acceder a una variable local.
Aquí hay algunos enlaces que explican esto con un poco más de profundidad:
http://developer.android.com/training/articles/perf-tips.html#GettersSetters
http://blog.leocad.io/why-you-shouldnt-use-getters-and-setters-on-android/
Es importante saber lo que estás tratando de lograr:
- El valor del campo debe ser accesible para el código del cliente, utilizando una interfaz pública.
- El campo está destinado a ser utilizado por subclases.
En una simple versión de Java, getters y setters logran ambas tareas. Pero Android es diferente. Si está haciendo # 1, entonces debe usar getters y setters públicos. Si está haciendo # 2, entonces debería usar campos protegidos. Si estás haciendo ambas cosas, usa ambas.
Si de todos modos va a haber un getter público, ¿por qué querría exponer el campo en sí más de lo estrictamente necesario? Eso significa que se puede escribir inmediatamente por subclases (a menos que sea final para comenzar).
Personalmente, me gusta que todos mis campos sean privados: proporciona una separación más clara entre la API y la implementación. Considero que la relación entre una superclase y una subclase es similar a la de una persona que llama y llama: los cambios en la implementación subyacente no deberían romper las subclases más de lo que deberían interrumpir a las personas que llaman. El nombre de un campo es un detalle de implementación que no debería afectar otras clases.
Es cierto que mi punto de vista se ve de vez en cuando como algo extremo ...
Siempre debe programar contra la API pública de una clase, es decir, usar los métodos públicos.
El motivo es simple Algún día en el futuro, usted u otra persona podrían querer cambiar la implementación. Esto siempre debería ser posible. Si confías en la variable de instancia, te limitas.
Además, al acceder a la variable, no puede controlar si esa variable es de solo lectura ni puede agregar cheques cuando se cambie esta variable.
Si usa setters / getters, siempre puede agregar validación, verificar etc. más adelante. También puede proporcionar un getter para que solo una variable sea de solo lectura.
El acceso directo al campo no es preferido. Utilice setters y getters public
o protected
.
El comprador no necesita ser public
: si quiere ocultar los datos de "personas externas", pero proporcione los datos a las subclases, use